Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- lib/python3.12/site-packages/transformers/models/aya_vision/__init__.py +28 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/configuration_aya_vision.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/modeling_aya_vision.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/modular_aya_vision.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/processing_aya_vision.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/configuration_aya_vision.py +109 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/modeling_aya_vision.py +555 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/modular_aya_vision.py +300 -0
- lib/python3.12/site-packages/transformers/models/aya_vision/processing_aya_vision.py +252 -0
- lib/python3.12/site-packages/transformers/models/bert_japanese/__init__.py +26 -0
- lib/python3.12/site-packages/transformers/models/bert_japanese/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/bert_japanese/__pycache__/tokenization_bert_japanese.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/bert_japanese/tokenization_bert_japanese.py +982 -0
- lib/python3.12/site-packages/transformers/models/bigbird_pegasus/__init__.py +27 -0
- lib/python3.12/site-packages/transformers/models/bigbird_pegasus/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/bigbird_pegasus/__pycache__/configuration_bigbird_pegasus.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/bigbird_pegasus/configuration_bigbird_pegasus.py +412 -0
- lib/python3.12/site-packages/transformers/models/bigbird_pegasus/modeling_bigbird_pegasus.py +0 -0
- lib/python3.12/site-packages/transformers/models/bros/__init__.py +28 -0
- lib/python3.12/site-packages/transformers/models/bros/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/bros/__pycache__/configuration_bros.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/bros/__pycache__/modeling_bros.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/bros/__pycache__/processing_bros.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/bros/configuration_bros.py +138 -0
- lib/python3.12/site-packages/transformers/models/bros/modeling_bros.py +1323 -0
- lib/python3.12/site-packages/transformers/models/bros/processing_bros.py +112 -0
- lib/python3.12/site-packages/transformers/models/clip/__init__.py +35 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/configuration_clip.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/feature_extraction_clip.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/image_processing_clip.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/image_processing_clip_fast.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/modeling_clip.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/modeling_flax_clip.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/modeling_tf_clip.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/processing_clip.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/tokenization_clip.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/__pycache__/tokenization_clip_fast.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/transformers/models/clip/configuration_clip.py +422 -0
- lib/python3.12/site-packages/transformers/models/clip/feature_extraction_clip.py +36 -0
- lib/python3.12/site-packages/transformers/models/clip/image_processing_clip.py +348 -0
- lib/python3.12/site-packages/transformers/models/clip/image_processing_clip_fast.py +42 -0
- lib/python3.12/site-packages/transformers/models/clip/modeling_clip.py +1645 -0
- lib/python3.12/site-packages/transformers/models/clip/modeling_flax_clip.py +1306 -0
- lib/python3.12/site-packages/transformers/models/clip/modeling_tf_clip.py +1460 -0
- lib/python3.12/site-packages/transformers/models/clip/processing_clip.py +156 -0
- lib/python3.12/site-packages/transformers/models/clip/tokenization_clip.py +519 -0
- lib/python3.12/site-packages/transformers/models/clip/tokenization_clip_fast.py +164 -0
- lib/python3.12/site-packages/transformers/models/colpali/__init__.py +28 -0
lib/python3.12/site-packages/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__)
|
lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (715 Bytes). View file
|
|
|
lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/configuration_aya_vision.cpython-312.pyc
ADDED
|
Binary file (4.2 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/modeling_aya_vision.cpython-312.pyc
ADDED
|
Binary file (29.7 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/modular_aya_vision.cpython-312.pyc
ADDED
|
Binary file (16.3 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/aya_vision/__pycache__/processing_aya_vision.cpython-312.pyc
ADDED
|
Binary file (11.2 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/aya_vision/configuration_aya_vision.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2025 Cohere team. All rights reserved.
|
| 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 |
+
"""AyaVision model configuration"""
|
| 16 |
+
|
| 17 |
+
from ...configuration_utils import PretrainedConfig
|
| 18 |
+
from ...utils import logging
|
| 19 |
+
from ..auto import CONFIG_MAPPING, AutoConfig
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
logger = logging.get_logger(__name__)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class AyaVisionConfig(PretrainedConfig):
|
| 26 |
+
r"""
|
| 27 |
+
This is the configuration class to store the configuration of a [`AyaVisionForConditionalGeneration`]. It is used to instantiate an
|
| 28 |
+
AyaVision model according to the specified arguments, defining the model architecture. Instantiating a configuration
|
| 29 |
+
with the defaults will yield a similar configuration to that of AyaVision.
|
| 30 |
+
e.g. [CohereForAI/aya-vision-8b](https://huggingface.co/CohereForAI/aya-vision-8b)
|
| 31 |
+
|
| 32 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 33 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 34 |
+
|
| 35 |
+
Args:
|
| 36 |
+
vision_config (`Union[AutoConfig, dict]`, *optional*, defaults to `CLIPVisionConfig`):
|
| 37 |
+
The config object or dictionary of the vision backbone.
|
| 38 |
+
text_config (`Union[AutoConfig, dict]`, *optional*, defaults to `LlamaConfig`):
|
| 39 |
+
The config object or dictionary of the text backbone.
|
| 40 |
+
vision_feature_select_strategy (`str`, *optional*, defaults to `"full"`):
|
| 41 |
+
The feature selection strategy used to select the vision feature from the vision backbone.
|
| 42 |
+
Can be one of `"default"` or `"full"`. If `"default"`, the CLS token is removed from the vision features.
|
| 43 |
+
If `"full"`, the full vision features are used.
|
| 44 |
+
vision_feature_layer (`int`, *optional*, defaults to -1):
|
| 45 |
+
The index of the layer to select the vision feature.
|
| 46 |
+
downsample_factor (`int`, *optional*, defaults to 2):
|
| 47 |
+
The downsample factor to apply to the vision features.
|
| 48 |
+
adapter_layer_norm_eps (`float`, *optional*, defaults to 1e-06):
|
| 49 |
+
The epsilon value used for layer normalization in the adapter.
|
| 50 |
+
image_token_index (`int`, *optional*, defaults to 255036):
|
| 51 |
+
The image token index to encode the image prompt.
|
| 52 |
+
"""
|
| 53 |
+
|
| 54 |
+
model_type = "aya_vision"
|
| 55 |
+
sub_configs = {"text_config": AutoConfig, "vision_config": AutoConfig}
|
| 56 |
+
|
| 57 |
+
def __init__(
|
| 58 |
+
self,
|
| 59 |
+
vision_config=None,
|
| 60 |
+
text_config=None,
|
| 61 |
+
vision_feature_select_strategy="full",
|
| 62 |
+
vision_feature_layer=-1,
|
| 63 |
+
downsample_factor=2,
|
| 64 |
+
adapter_layer_norm_eps=1e-6,
|
| 65 |
+
image_token_index=255036,
|
| 66 |
+
**kwargs,
|
| 67 |
+
):
|
| 68 |
+
self.image_token_index = image_token_index
|
| 69 |
+
self.downsample_factor = downsample_factor
|
| 70 |
+
self.adapter_layer_norm_eps = adapter_layer_norm_eps
|
| 71 |
+
if vision_feature_select_strategy not in ["default", "full"]:
|
| 72 |
+
raise ValueError(
|
| 73 |
+
"vision_feature_select_strategy should be one of 'default', 'full'."
|
| 74 |
+
f"Got: {vision_feature_select_strategy}"
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
self.vision_feature_select_strategy = vision_feature_select_strategy
|
| 78 |
+
self.vision_feature_layer = vision_feature_layer
|
| 79 |
+
|
| 80 |
+
if isinstance(vision_config, dict):
|
| 81 |
+
vision_config["model_type"] = (
|
| 82 |
+
vision_config["model_type"] if "model_type" in vision_config else "clip_vision_model"
|
| 83 |
+
)
|
| 84 |
+
vision_config = CONFIG_MAPPING[vision_config["model_type"]](**vision_config)
|
| 85 |
+
elif vision_config is None:
|
| 86 |
+
vision_config = CONFIG_MAPPING["siglip_vision_model"](
|
| 87 |
+
hidden_size=1152,
|
| 88 |
+
intermediate_size=4304,
|
| 89 |
+
patch_size=14,
|
| 90 |
+
image_size=384,
|
| 91 |
+
num_hidden_layers=26,
|
| 92 |
+
num_attention_heads=14,
|
| 93 |
+
vision_use_head=False,
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
self.vision_config = vision_config
|
| 97 |
+
|
| 98 |
+
if isinstance(text_config, dict):
|
| 99 |
+
text_config["model_type"] = text_config["model_type"] if "model_type" in text_config else "llama"
|
| 100 |
+
text_config = CONFIG_MAPPING[text_config["model_type"]](**text_config)
|
| 101 |
+
elif text_config is None:
|
| 102 |
+
text_config = CONFIG_MAPPING["cohere2"]()
|
| 103 |
+
|
| 104 |
+
self.text_config = text_config
|
| 105 |
+
|
| 106 |
+
super().__init__(**kwargs)
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
__all__ = ["AyaVisionConfig"]
|
lib/python3.12/site-packages/transformers/models/aya_vision/modeling_aya_vision.py
ADDED
|
@@ -0,0 +1,555 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
# coding=utf-8
|
| 8 |
+
# Copyright 2025 the Cohere Inc. team. All rights reserved.
|
| 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 |
+
|
| 22 |
+
from dataclasses import dataclass
|
| 23 |
+
from typing import List, Optional, Tuple, Union
|
| 24 |
+
|
| 25 |
+
import torch
|
| 26 |
+
from torch import nn
|
| 27 |
+
|
| 28 |
+
from ...activations import ACT2FN
|
| 29 |
+
from ...generation import GenerationMixin
|
| 30 |
+
from ...modeling_outputs import ModelOutput
|
| 31 |
+
from ...modeling_utils import PreTrainedModel
|
| 32 |
+
from ...utils import (
|
| 33 |
+
add_start_docstrings,
|
| 34 |
+
add_start_docstrings_to_model_forward,
|
| 35 |
+
is_torchdynamo_compiling,
|
| 36 |
+
replace_return_docstrings,
|
| 37 |
+
)
|
| 38 |
+
from ...utils.deprecation import deprecate_kwarg
|
| 39 |
+
from ..auto import AutoModel, AutoModelForCausalLM
|
| 40 |
+
from .configuration_aya_vision import AyaVisionConfig
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
_CONFIG_FOR_DOC = "AyaVisionConfig"
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class AyaVisionMultiModalProjector(nn.Module):
|
| 47 |
+
def __init__(self, config: AyaVisionConfig):
|
| 48 |
+
super().__init__()
|
| 49 |
+
self.config = config
|
| 50 |
+
self.downsample_factor = config.downsample_factor
|
| 51 |
+
self.alignment_intermediate_size = getattr(
|
| 52 |
+
config, "alignment_intermediate_size", config.text_config.hidden_size
|
| 53 |
+
)
|
| 54 |
+
self.layernorm = nn.LayerNorm(
|
| 55 |
+
config.vision_config.hidden_size * (config.downsample_factor**2), eps=config.adapter_layer_norm_eps
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
self.linear_1 = nn.Linear(
|
| 59 |
+
config.vision_config.hidden_size * (config.downsample_factor**2),
|
| 60 |
+
self.alignment_intermediate_size,
|
| 61 |
+
bias=True,
|
| 62 |
+
)
|
| 63 |
+
|
| 64 |
+
self.act = ACT2FN["silu"] # SwiGLU uses SiLU activation
|
| 65 |
+
# For SwiGLU, project down to half size since we split intermediate dim
|
| 66 |
+
self.linear_2 = nn.Linear(self.alignment_intermediate_size // 2, config.text_config.hidden_size, bias=True)
|
| 67 |
+
|
| 68 |
+
def forward(self, image_features):
|
| 69 |
+
image_features = self.pixel_shuffle(image_features)
|
| 70 |
+
image_features = self.layernorm(image_features)
|
| 71 |
+
hidden_states = self.linear_1(image_features)
|
| 72 |
+
|
| 73 |
+
# Split along last dimension and apply SwiGLU
|
| 74 |
+
x, gate = hidden_states.chunk(2, dim=-1)
|
| 75 |
+
hidden_states = self.act(gate) * x
|
| 76 |
+
|
| 77 |
+
hidden_states = self.linear_2(hidden_states)
|
| 78 |
+
return hidden_states
|
| 79 |
+
|
| 80 |
+
def pixel_shuffle(self, image_features): # B, S, D
|
| 81 |
+
batch_size, seq_length, feature_dim = image_features.shape
|
| 82 |
+
height = width = int(seq_length**0.5)
|
| 83 |
+
image_features = image_features.reshape(image_features.shape[0], width, height, -1)
|
| 84 |
+
channels = image_features.shape[-1]
|
| 85 |
+
image_features = image_features.reshape(
|
| 86 |
+
batch_size, width, int(height / self.downsample_factor), int(channels * self.downsample_factor)
|
| 87 |
+
)
|
| 88 |
+
image_features = image_features.permute(0, 2, 1, 3)
|
| 89 |
+
image_features = image_features.reshape(
|
| 90 |
+
batch_size, int(height / self.downsample_factor), int(width / self.downsample_factor), -1
|
| 91 |
+
)
|
| 92 |
+
image_features = image_features.permute(0, 2, 1, 3)
|
| 93 |
+
return image_features
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
AYA_VISION_START_DOCSTRING = r"""
|
| 97 |
+
This model inherits from [`PreTrainedModel`]. Check the superclass documentation for the generic methods the
|
| 98 |
+
library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads
|
| 99 |
+
etc.)
|
| 100 |
+
|
| 101 |
+
This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass.
|
| 102 |
+
Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage
|
| 103 |
+
and behavior.
|
| 104 |
+
|
| 105 |
+
Parameters:
|
| 106 |
+
config ([`AyaVisionConfig`] or [`AyaVisionVisionConfig`]):
|
| 107 |
+
Model configuration class with all the parameters of the model. Initializing with a config file does not
|
| 108 |
+
load the weights associated with the model, only the configuration. Check out the
|
| 109 |
+
[`~PreTrainedModel.from_pretrained`] method to load the model weights.
|
| 110 |
+
"""
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
@add_start_docstrings(
|
| 114 |
+
"The bare Aya Vision Model outputting raw hidden-states without any specific head on top.",
|
| 115 |
+
AYA_VISION_START_DOCSTRING,
|
| 116 |
+
)
|
| 117 |
+
class AyaVisionPreTrainedModel(PreTrainedModel):
|
| 118 |
+
config_class = AyaVisionConfig
|
| 119 |
+
base_model_prefix = "model"
|
| 120 |
+
supports_gradient_checkpointing = True
|
| 121 |
+
_no_split_modules = ["AyaVisionVisionAttention"]
|
| 122 |
+
_skip_keys_device_placement = "past_key_values"
|
| 123 |
+
_supports_cache_class = True
|
| 124 |
+
_supports_flash_attn_2 = True
|
| 125 |
+
_supports_sdpa = True
|
| 126 |
+
_supports_quantized_cache = False
|
| 127 |
+
_supports_static_cache = False
|
| 128 |
+
|
| 129 |
+
def _init_weights(self, module):
|
| 130 |
+
# important: this ported version of AyaVision isn't meant for training from scratch - only
|
| 131 |
+
# inference and fine-tuning - so the proper init weights code has been removed - the original codebase
|
| 132 |
+
# https://github.com/haotian-liu/AyaVision/tree/main/aya_vision should serve for that purpose
|
| 133 |
+
std = (
|
| 134 |
+
self.config.initializer_range
|
| 135 |
+
if hasattr(self.config, "initializer_range")
|
| 136 |
+
else self.config.text_config.initializer_range
|
| 137 |
+
)
|
| 138 |
+
|
| 139 |
+
if hasattr(module, "class_embedding"):
|
| 140 |
+
module.class_embedding.data.normal_(mean=0.0, std=std)
|
| 141 |
+
|
| 142 |
+
if isinstance(module, (nn.Linear, nn.Conv2d)):
|
| 143 |
+
module.weight.data.normal_(mean=0.0, std=std)
|
| 144 |
+
if module.bias is not None:
|
| 145 |
+
module.bias.data.zero_()
|
| 146 |
+
elif isinstance(module, nn.Embedding):
|
| 147 |
+
module.weight.data.normal_(mean=0.0, std=std)
|
| 148 |
+
if module.padding_idx is not None:
|
| 149 |
+
module.weight.data[module.padding_idx].zero_()
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
@dataclass
|
| 153 |
+
class AyaVisionCausalLMOutputWithPast(ModelOutput):
|
| 154 |
+
"""
|
| 155 |
+
Base class for AyaVision causal language model (or autoregressive) outputs.
|
| 156 |
+
|
| 157 |
+
Args:
|
| 158 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` is provided):
|
| 159 |
+
Language modeling loss (for next-token prediction).
|
| 160 |
+
logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.vocab_size)`):
|
| 161 |
+
Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
|
| 162 |
+
past_key_values (`tuple(tuple(torch.FloatTensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
|
| 163 |
+
Tuple of `tuple(torch.FloatTensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape
|
| 164 |
+
`(batch_size, num_heads, sequence_length, embed_size_per_head)`)
|
| 165 |
+
|
| 166 |
+
Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see
|
| 167 |
+
`past_key_values` input) to speed up sequential decoding.
|
| 168 |
+
hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
|
| 169 |
+
Tuple of `torch.FloatTensor` (one for the output of the embeddings, if the model has an embedding layer, +
|
| 170 |
+
one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.
|
| 171 |
+
|
| 172 |
+
Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.
|
| 173 |
+
attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
|
| 174 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 175 |
+
sequence_length)`.
|
| 176 |
+
|
| 177 |
+
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
| 178 |
+
heads.
|
| 179 |
+
image_hidden_states (`torch.FloatTensor`, *optional*):
|
| 180 |
+
A `torch.FloatTensor` of size (batch_size, num_images, sequence_length, hidden_size)`.
|
| 181 |
+
image_hidden_states of the model produced by the vision encoder and after projecting the last hidden state.
|
| 182 |
+
"""
|
| 183 |
+
|
| 184 |
+
loss: Optional[torch.FloatTensor] = None
|
| 185 |
+
logits: Optional[torch.FloatTensor] = None
|
| 186 |
+
past_key_values: Optional[List[torch.FloatTensor]] = None
|
| 187 |
+
hidden_states: Optional[Tuple[torch.FloatTensor]] = None
|
| 188 |
+
attentions: Optional[Tuple[torch.FloatTensor]] = None
|
| 189 |
+
image_hidden_states: Optional[torch.FloatTensor] = None
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
AYA_VISION_INPUTS_DOCSTRING = """
|
| 193 |
+
Args:
|
| 194 |
+
input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
|
| 195 |
+
Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
|
| 196 |
+
it.
|
| 197 |
+
|
| 198 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 199 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 200 |
+
|
| 201 |
+
[What are input IDs?](../glossary#input-ids)
|
| 202 |
+
pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size)):
|
| 203 |
+
The tensors corresponding to the input images. Pixel values can be obtained using
|
| 204 |
+
[`AutoImageProcessor`]. See [`GotOcr2ImageProcessor.__call__`] for details. [`AyaVisionProcessor`] uses
|
| 205 |
+
[`GotOcr2ImageProcessor`] for processing images.
|
| 206 |
+
attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 207 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 208 |
+
|
| 209 |
+
- 1 for tokens that are **not masked**,
|
| 210 |
+
- 0 for tokens that are **masked**.
|
| 211 |
+
|
| 212 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 213 |
+
|
| 214 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 215 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 216 |
+
|
| 217 |
+
If `past_key_values` is used, optionally only the last `decoder_input_ids` have to be input (see
|
| 218 |
+
`past_key_values`).
|
| 219 |
+
|
| 220 |
+
If you want to change padding behavior, you should read [`modeling_opt._prepare_decoder_attention_mask`]
|
| 221 |
+
and modify to your needs. See diagram 1 in [the paper](https://arxiv.org/abs/1910.13461) for more
|
| 222 |
+
information on the default strategy.
|
| 223 |
+
|
| 224 |
+
- 1 indicates the head is **not masked**,
|
| 225 |
+
- 0 indicates the head is **masked**.
|
| 226 |
+
position_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 227 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 228 |
+
config.n_positions - 1]`. [What are position IDs?](../glossary#position-ids)
|
| 229 |
+
past_key_values (`tuple(tuple(torch.FloatTensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
|
| 230 |
+
Tuple of `tuple(torch.FloatTensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape
|
| 231 |
+
`(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape
|
| 232 |
+
`(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.
|
| 233 |
+
|
| 234 |
+
Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention
|
| 235 |
+
blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.
|
| 236 |
+
|
| 237 |
+
If `past_key_values` are used, the user can optionally input only the last `decoder_input_ids` (those that
|
| 238 |
+
don't have their past key value states given to this model) of shape `(batch_size, 1)` instead of all
|
| 239 |
+
`decoder_input_ids` of shape `(batch_size, sequence_length)`.
|
| 240 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
|
| 241 |
+
Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation. This
|
| 242 |
+
is useful if you want more control over how to convert `input_ids` indices into associated vectors than the
|
| 243 |
+
model's internal embedding lookup matrix.
|
| 244 |
+
vision_feature_layer (`Union[int, List[int]], *optional*, defaults to -2`):
|
| 245 |
+
The index of the layer to select the vision feature. If multiple indices are provided,
|
| 246 |
+
the vision feature of the corresponding indices will be concatenated to form the
|
| 247 |
+
vision features.
|
| 248 |
+
vision_feature_select_strategy (`str`, *optional*, defaults to `"default"`):
|
| 249 |
+
The feature selection strategy used to select the vision feature from the vision backbone.
|
| 250 |
+
Can be one of `"default"` or `"full"`.
|
| 251 |
+
use_cache (`bool`, *optional*):
|
| 252 |
+
If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding (see
|
| 253 |
+
`past_key_values`).
|
| 254 |
+
output_attentions (`bool`, *optional*):
|
| 255 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 256 |
+
tensors for more detail.
|
| 257 |
+
output_hidden_states (`bool`, *optional*):
|
| 258 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 259 |
+
more detail.
|
| 260 |
+
return_dict (`bool`, *optional*):
|
| 261 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 262 |
+
cache_position (`torch.LongTensor` of shape `(sequence_length)`, *optional*):
|
| 263 |
+
Indices depicting the position of the input sequence tokens in the sequence. Contrarily to `position_ids`,
|
| 264 |
+
this tensor is not affected by padding. It is used to update the cache in the correct position and to infer
|
| 265 |
+
the complete sequence length.
|
| 266 |
+
"""
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
@add_start_docstrings(
|
| 270 |
+
"""The AyaVision model which consists of a vision backbone and a language model.""",
|
| 271 |
+
AYA_VISION_START_DOCSTRING,
|
| 272 |
+
)
|
| 273 |
+
class AyaVisionForConditionalGeneration(AyaVisionPreTrainedModel, GenerationMixin):
|
| 274 |
+
def __init__(self, config: AyaVisionConfig):
|
| 275 |
+
super().__init__(config)
|
| 276 |
+
self.vision_tower = AutoModel.from_config(config.vision_config)
|
| 277 |
+
|
| 278 |
+
self.multi_modal_projector = AyaVisionMultiModalProjector(config)
|
| 279 |
+
self.vocab_size = config.text_config.vocab_size
|
| 280 |
+
self.language_model = AutoModelForCausalLM.from_config(config.text_config)
|
| 281 |
+
|
| 282 |
+
if self.language_model._tied_weights_keys is not None:
|
| 283 |
+
self._tied_weights_keys = [f"language_model.{k}" for k in self.language_model._tied_weights_keys]
|
| 284 |
+
|
| 285 |
+
self.pad_token_id = self.config.pad_token_id if self.config.pad_token_id is not None else -1
|
| 286 |
+
|
| 287 |
+
self.post_init()
|
| 288 |
+
|
| 289 |
+
def get_input_embeddings(self):
|
| 290 |
+
return self.language_model.get_input_embeddings()
|
| 291 |
+
|
| 292 |
+
def set_input_embeddings(self, value):
|
| 293 |
+
self.language_model.set_input_embeddings(value)
|
| 294 |
+
|
| 295 |
+
def get_output_embeddings(self):
|
| 296 |
+
return self.language_model.get_output_embeddings()
|
| 297 |
+
|
| 298 |
+
def set_output_embeddings(self, new_embeddings):
|
| 299 |
+
self.language_model.set_output_embeddings(new_embeddings)
|
| 300 |
+
|
| 301 |
+
def set_decoder(self, decoder):
|
| 302 |
+
self.language_model.set_decoder(decoder)
|
| 303 |
+
|
| 304 |
+
def get_decoder(self):
|
| 305 |
+
return self.language_model.get_decoder()
|
| 306 |
+
|
| 307 |
+
def get_image_features(
|
| 308 |
+
self,
|
| 309 |
+
pixel_values: torch.FloatTensor,
|
| 310 |
+
vision_feature_layer: Union[int, List[int]],
|
| 311 |
+
vision_feature_select_strategy: str,
|
| 312 |
+
**kwargs,
|
| 313 |
+
):
|
| 314 |
+
"""
|
| 315 |
+
Obtains image last hidden states from the vision tower and apply multimodal projection.
|
| 316 |
+
|
| 317 |
+
Args:
|
| 318 |
+
pixel_values (`torch.FloatTensor]` of shape `(batch_size, channels, height, width)`)
|
| 319 |
+
The tensors corresponding to the input images.
|
| 320 |
+
vision_feature_layer (`Union[int, List[int]]`):
|
| 321 |
+
The index of the layer to select the vision feature. If multiple indices are provided,
|
| 322 |
+
the vision feature of the corresponding indices will be concatenated to form the
|
| 323 |
+
vision features.
|
| 324 |
+
vision_feature_select_strategy (`str`):
|
| 325 |
+
The feature selection strategy used to select the vision feature from the vision backbone.
|
| 326 |
+
Can be one of `"default"` or `"full"`
|
| 327 |
+
Returns:
|
| 328 |
+
image_features (`torch.Tensor`): Image feature tensor of shape `(num_images, image_length, embed_dim)`).
|
| 329 |
+
"""
|
| 330 |
+
if vision_feature_select_strategy not in ["default", "full"]:
|
| 331 |
+
raise ValueError(f"Unexpected select feature strategy: {self.config.vision_feature_select_strategy}")
|
| 332 |
+
|
| 333 |
+
kwargs = {k: v for k, v in kwargs.items() if v is not None}
|
| 334 |
+
# this is not memory efficient at all (output_hidden_states=True) will save all the hidden states.
|
| 335 |
+
image_outputs = self.vision_tower(pixel_values, output_hidden_states=True, **kwargs)
|
| 336 |
+
|
| 337 |
+
# If we have one vision feature layer, return the corresponding hidden states,
|
| 338 |
+
# otherwise, select the hidden states of each feature layer and concatenate them
|
| 339 |
+
if isinstance(vision_feature_layer, int):
|
| 340 |
+
selected_image_feature = image_outputs.hidden_states[vision_feature_layer]
|
| 341 |
+
if vision_feature_select_strategy == "default":
|
| 342 |
+
selected_image_feature = selected_image_feature[:, 1:]
|
| 343 |
+
else:
|
| 344 |
+
hs_pool = [image_outputs.hidden_states[layer_idx] for layer_idx in vision_feature_layer]
|
| 345 |
+
# For default; crop CLS from each hidden state in the hidden state pool
|
| 346 |
+
if vision_feature_select_strategy == "default":
|
| 347 |
+
hs_pool = [hs[:, 1:] for hs in hs_pool]
|
| 348 |
+
selected_image_feature = torch.cat(hs_pool, dim=-1)
|
| 349 |
+
|
| 350 |
+
image_features = self.multi_modal_projector(selected_image_feature)
|
| 351 |
+
return image_features
|
| 352 |
+
|
| 353 |
+
@deprecate_kwarg("num_logits_to_keep", version="4.50", new_name="logits_to_keep")
|
| 354 |
+
@add_start_docstrings_to_model_forward(AYA_VISION_INPUTS_DOCSTRING)
|
| 355 |
+
@replace_return_docstrings(output_type=AyaVisionCausalLMOutputWithPast, config_class=_CONFIG_FOR_DOC)
|
| 356 |
+
def forward(
|
| 357 |
+
self,
|
| 358 |
+
input_ids: Optional[torch.LongTensor] = None,
|
| 359 |
+
pixel_values: Optional[torch.FloatTensor] = None,
|
| 360 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 361 |
+
position_ids: Optional[torch.LongTensor] = None,
|
| 362 |
+
past_key_values: Optional[List[torch.FloatTensor]] = None,
|
| 363 |
+
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 364 |
+
vision_feature_layer: Optional[Union[int, List[int]]] = None,
|
| 365 |
+
vision_feature_select_strategy: Optional[str] = None,
|
| 366 |
+
labels: Optional[torch.LongTensor] = None,
|
| 367 |
+
use_cache: Optional[bool] = None,
|
| 368 |
+
output_attentions: Optional[bool] = None,
|
| 369 |
+
output_hidden_states: Optional[bool] = None,
|
| 370 |
+
return_dict: Optional[bool] = None,
|
| 371 |
+
cache_position: Optional[torch.LongTensor] = None,
|
| 372 |
+
logits_to_keep: Union[int, torch.Tensor] = 0,
|
| 373 |
+
image_sizes: Optional[torch.Tensor] = None,
|
| 374 |
+
**lm_kwargs,
|
| 375 |
+
) -> Union[Tuple, AyaVisionCausalLMOutputWithPast]:
|
| 376 |
+
r"""
|
| 377 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 378 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 379 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 380 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 381 |
+
|
| 382 |
+
logits_to_keep (`int` or `torch.Tensor`, *optional*):
|
| 383 |
+
If an `int`, compute logits for the last `logits_to_keep` tokens. If `0`, calculate logits for all
|
| 384 |
+
`input_ids` (special case). Only last token logits are needed for generation, and calculating them only for that
|
| 385 |
+
token can save memory, which becomes pretty significant for long sequences or large vocabulary size.
|
| 386 |
+
If a `torch.Tensor`, must be 1D corresponding to the indices to keep in the sequence length dimension.
|
| 387 |
+
This is useful when using packed tensor format (single dimension for batch and sequence length).
|
| 388 |
+
|
| 389 |
+
|
| 390 |
+
Returns:
|
| 391 |
+
|
| 392 |
+
Example:
|
| 393 |
+
|
| 394 |
+
```python
|
| 395 |
+
>>> from transformers import AutoProcessor, AyaVisionForConditionalGeneration
|
| 396 |
+
>>> import torch
|
| 397 |
+
|
| 398 |
+
>>> torch_device = "cuda:0"
|
| 399 |
+
>>> processor = AutoProcessor.from_pretrained("CohereForAI/aya-vision-8b", use_fast=True)
|
| 400 |
+
>>> model = AyaVisionForConditionalGeneration.from_pretrained("CohereForAI/aya-vision-8b", device_map=torch_device)
|
| 401 |
+
|
| 402 |
+
>>> messages = [
|
| 403 |
+
... {
|
| 404 |
+
... "role": "user",
|
| 405 |
+
... "content": [
|
| 406 |
+
... {
|
| 407 |
+
... "type": "image",
|
| 408 |
+
... "url": "https://pbs.twimg.com/media/Fx7YvfQWYAIp6rZ?format=jpg&name=medium",
|
| 409 |
+
... },
|
| 410 |
+
... {"type": "text", "text": "चित्र में लिखा पाठ क्या कहता है?"},
|
| 411 |
+
... ],
|
| 412 |
+
... }
|
| 413 |
+
... ]
|
| 414 |
+
|
| 415 |
+
>>> inputs = processor.apply_chat_template(
|
| 416 |
+
... messages, padding=True, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", device=torch_device
|
| 417 |
+
... ).to(model.device)
|
| 418 |
+
|
| 419 |
+
>>> gen_tokens = model.generate(**inputs, max_new_tokens=300, do_sample=True, temperature=0.3)
|
| 420 |
+
>>> processor.tokenizer.decode(gen_tokens[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
|
| 421 |
+
```"""
|
| 422 |
+
|
| 423 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 424 |
+
output_hidden_states = (
|
| 425 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 426 |
+
)
|
| 427 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 428 |
+
vision_feature_layer = (
|
| 429 |
+
vision_feature_layer if vision_feature_layer is not None else self.config.vision_feature_layer
|
| 430 |
+
)
|
| 431 |
+
vision_feature_select_strategy = (
|
| 432 |
+
vision_feature_select_strategy
|
| 433 |
+
if vision_feature_select_strategy is not None
|
| 434 |
+
else self.config.vision_feature_select_strategy
|
| 435 |
+
)
|
| 436 |
+
|
| 437 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 438 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 439 |
+
|
| 440 |
+
if pixel_values is not None and inputs_embeds is not None:
|
| 441 |
+
raise ValueError(
|
| 442 |
+
"You cannot specify both pixel_values and inputs_embeds at the same time, and must specify either one"
|
| 443 |
+
)
|
| 444 |
+
|
| 445 |
+
if inputs_embeds is None:
|
| 446 |
+
inputs_embeds = self.get_input_embeddings()(input_ids)
|
| 447 |
+
|
| 448 |
+
if pixel_values is not None:
|
| 449 |
+
image_features = self.get_image_features(
|
| 450 |
+
pixel_values=pixel_values,
|
| 451 |
+
vision_feature_layer=vision_feature_layer,
|
| 452 |
+
vision_feature_select_strategy=vision_feature_select_strategy,
|
| 453 |
+
image_sizes=image_sizes,
|
| 454 |
+
)
|
| 455 |
+
|
| 456 |
+
special_image_mask = (input_ids == self.config.image_token_index).unsqueeze(-1)
|
| 457 |
+
special_image_mask = special_image_mask.expand_as(inputs_embeds).to(inputs_embeds.device)
|
| 458 |
+
if not is_torchdynamo_compiling() and inputs_embeds[special_image_mask].numel() != image_features.numel():
|
| 459 |
+
n_image_tokens = (input_ids == self.config.image_token_index).sum()
|
| 460 |
+
n_image_features = image_features.shape[0] * image_features.shape[1]
|
| 461 |
+
raise ValueError(
|
| 462 |
+
f"Image features and image tokens do not match: tokens: {n_image_tokens}, features {n_image_features}"
|
| 463 |
+
)
|
| 464 |
+
image_features = image_features.to(inputs_embeds.device, inputs_embeds.dtype)
|
| 465 |
+
inputs_embeds = inputs_embeds.masked_scatter(special_image_mask, image_features)
|
| 466 |
+
|
| 467 |
+
outputs = self.language_model(
|
| 468 |
+
attention_mask=attention_mask,
|
| 469 |
+
position_ids=position_ids,
|
| 470 |
+
past_key_values=past_key_values,
|
| 471 |
+
inputs_embeds=inputs_embeds,
|
| 472 |
+
use_cache=use_cache,
|
| 473 |
+
output_attentions=output_attentions,
|
| 474 |
+
output_hidden_states=output_hidden_states,
|
| 475 |
+
return_dict=return_dict,
|
| 476 |
+
cache_position=cache_position,
|
| 477 |
+
logits_to_keep=logits_to_keep,
|
| 478 |
+
**lm_kwargs,
|
| 479 |
+
)
|
| 480 |
+
|
| 481 |
+
logits = outputs[0]
|
| 482 |
+
|
| 483 |
+
loss = None
|
| 484 |
+
if labels is not None:
|
| 485 |
+
# Shift so that tokens < n predict n
|
| 486 |
+
if attention_mask is not None:
|
| 487 |
+
# we use the input attention mask to shift the logits and labels, because it is 2D.
|
| 488 |
+
# we also crop attn mask in case it is longer, which happens in PrefixTuning with peft
|
| 489 |
+
shift_attention_mask = attention_mask[:, -(logits.shape[1] - 1) :].to(logits.device)
|
| 490 |
+
shift_logits = logits[..., :-1, :][shift_attention_mask.to(logits.device) != 0].contiguous()
|
| 491 |
+
shift_labels = labels[..., 1:][shift_attention_mask.to(labels.device) != 0].contiguous()
|
| 492 |
+
else:
|
| 493 |
+
shift_logits = logits[..., :-1, :].contiguous()
|
| 494 |
+
shift_labels = labels[..., 1:].contiguous()
|
| 495 |
+
# Flatten the tokens
|
| 496 |
+
loss_fct = nn.CrossEntropyLoss()
|
| 497 |
+
loss = loss_fct(
|
| 498 |
+
shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1).to(shift_logits.device)
|
| 499 |
+
)
|
| 500 |
+
|
| 501 |
+
if not return_dict:
|
| 502 |
+
output = (logits,) + outputs[1:]
|
| 503 |
+
return (loss,) + output if loss is not None else output
|
| 504 |
+
|
| 505 |
+
return AyaVisionCausalLMOutputWithPast(
|
| 506 |
+
loss=loss,
|
| 507 |
+
logits=logits,
|
| 508 |
+
past_key_values=outputs.past_key_values,
|
| 509 |
+
hidden_states=outputs.hidden_states,
|
| 510 |
+
attentions=outputs.attentions,
|
| 511 |
+
image_hidden_states=image_features if pixel_values is not None else None,
|
| 512 |
+
)
|
| 513 |
+
|
| 514 |
+
def prepare_inputs_for_generation(
|
| 515 |
+
self,
|
| 516 |
+
input_ids,
|
| 517 |
+
past_key_values=None,
|
| 518 |
+
inputs_embeds=None,
|
| 519 |
+
pixel_values=None,
|
| 520 |
+
attention_mask=None,
|
| 521 |
+
cache_position=None,
|
| 522 |
+
logits_to_keep=None,
|
| 523 |
+
**kwargs,
|
| 524 |
+
):
|
| 525 |
+
# Overwritten -- in specific circumstances we don't want to forward image inputs to the model
|
| 526 |
+
|
| 527 |
+
model_inputs = self.language_model.prepare_inputs_for_generation(
|
| 528 |
+
input_ids,
|
| 529 |
+
past_key_values=past_key_values,
|
| 530 |
+
inputs_embeds=inputs_embeds,
|
| 531 |
+
attention_mask=attention_mask,
|
| 532 |
+
cache_position=cache_position,
|
| 533 |
+
logits_to_keep=logits_to_keep,
|
| 534 |
+
**kwargs,
|
| 535 |
+
)
|
| 536 |
+
|
| 537 |
+
if cache_position[0] == 0:
|
| 538 |
+
# If we're in cached decoding stage, pixel values should be None because input ids do not contain special image token anymore
|
| 539 |
+
# Otherwise we need pixel values to be passed to model
|
| 540 |
+
model_inputs["pixel_values"] = pixel_values
|
| 541 |
+
|
| 542 |
+
return model_inputs
|
| 543 |
+
|
| 544 |
+
def tie_weights(self):
|
| 545 |
+
return self.language_model.tie_weights()
|
| 546 |
+
|
| 547 |
+
def resize_token_embeddings(self, new_num_tokens: Optional[int] = None, pad_to_multiple_of=None) -> nn.Embedding:
|
| 548 |
+
model_embeds = self.language_model.resize_token_embeddings(new_num_tokens, pad_to_multiple_of)
|
| 549 |
+
# update vocab size
|
| 550 |
+
self.config.text_config.vocab_size = model_embeds.num_embeddings
|
| 551 |
+
self.vocab_size = model_embeds.num_embeddings
|
| 552 |
+
return model_embeds
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
__all__ = ["AyaVisionForConditionalGeneration", "AyaVisionPreTrainedModel"]
|
lib/python3.12/site-packages/transformers/models/aya_vision/modular_aya_vision.py
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2025 the Cohere Inc. team. All rights reserved.
|
| 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 |
+
"""PyTorch AyaVision model."""
|
| 16 |
+
|
| 17 |
+
from typing import List, Optional, Tuple, Union
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
from torch import nn
|
| 21 |
+
|
| 22 |
+
from transformers.models.llava.modeling_llava import (
|
| 23 |
+
LlavaCausalLMOutputWithPast,
|
| 24 |
+
LlavaForConditionalGeneration,
|
| 25 |
+
LlavaPreTrainedModel,
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
from ...activations import ACT2FN
|
| 29 |
+
from ...utils import (
|
| 30 |
+
add_start_docstrings,
|
| 31 |
+
logging,
|
| 32 |
+
)
|
| 33 |
+
from .configuration_aya_vision import AyaVisionConfig
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
logger = logging.get_logger(__name__)
|
| 37 |
+
|
| 38 |
+
_CONFIG_FOR_DOC = "AyaVisionConfig"
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class AyaVisionMultiModalProjector(nn.Module):
|
| 42 |
+
def __init__(self, config: AyaVisionConfig):
|
| 43 |
+
super().__init__()
|
| 44 |
+
self.config = config
|
| 45 |
+
self.downsample_factor = config.downsample_factor
|
| 46 |
+
self.alignment_intermediate_size = getattr(
|
| 47 |
+
config, "alignment_intermediate_size", config.text_config.hidden_size
|
| 48 |
+
)
|
| 49 |
+
self.layernorm = nn.LayerNorm(
|
| 50 |
+
config.vision_config.hidden_size * (config.downsample_factor**2), eps=config.adapter_layer_norm_eps
|
| 51 |
+
)
|
| 52 |
+
|
| 53 |
+
self.linear_1 = nn.Linear(
|
| 54 |
+
config.vision_config.hidden_size * (config.downsample_factor**2),
|
| 55 |
+
self.alignment_intermediate_size,
|
| 56 |
+
bias=True,
|
| 57 |
+
)
|
| 58 |
+
|
| 59 |
+
self.act = ACT2FN["silu"] # SwiGLU uses SiLU activation
|
| 60 |
+
# For SwiGLU, project down to half size since we split intermediate dim
|
| 61 |
+
self.linear_2 = nn.Linear(self.alignment_intermediate_size // 2, config.text_config.hidden_size, bias=True)
|
| 62 |
+
|
| 63 |
+
def forward(self, image_features):
|
| 64 |
+
image_features = self.pixel_shuffle(image_features)
|
| 65 |
+
image_features = self.layernorm(image_features)
|
| 66 |
+
hidden_states = self.linear_1(image_features)
|
| 67 |
+
|
| 68 |
+
# Split along last dimension and apply SwiGLU
|
| 69 |
+
x, gate = hidden_states.chunk(2, dim=-1)
|
| 70 |
+
hidden_states = self.act(gate) * x
|
| 71 |
+
|
| 72 |
+
hidden_states = self.linear_2(hidden_states)
|
| 73 |
+
return hidden_states
|
| 74 |
+
|
| 75 |
+
def pixel_shuffle(self, image_features): # B, S, D
|
| 76 |
+
batch_size, seq_length, feature_dim = image_features.shape
|
| 77 |
+
height = width = int(seq_length**0.5)
|
| 78 |
+
image_features = image_features.reshape(image_features.shape[0], width, height, -1)
|
| 79 |
+
channels = image_features.shape[-1]
|
| 80 |
+
image_features = image_features.reshape(
|
| 81 |
+
batch_size, width, int(height / self.downsample_factor), int(channels * self.downsample_factor)
|
| 82 |
+
)
|
| 83 |
+
image_features = image_features.permute(0, 2, 1, 3)
|
| 84 |
+
image_features = image_features.reshape(
|
| 85 |
+
batch_size, int(height / self.downsample_factor), int(width / self.downsample_factor), -1
|
| 86 |
+
)
|
| 87 |
+
image_features = image_features.permute(0, 2, 1, 3)
|
| 88 |
+
return image_features
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
AYA_VISION_START_DOCSTRING = r"""
|
| 92 |
+
This model inherits from [`PreTrainedModel`]. Check the superclass documentation for the generic methods the
|
| 93 |
+
library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads
|
| 94 |
+
etc.)
|
| 95 |
+
|
| 96 |
+
This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass.
|
| 97 |
+
Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage
|
| 98 |
+
and behavior.
|
| 99 |
+
|
| 100 |
+
Parameters:
|
| 101 |
+
config ([`AyaVisionConfig`] or [`AyaVisionVisionConfig`]):
|
| 102 |
+
Model configuration class with all the parameters of the model. Initializing with a config file does not
|
| 103 |
+
load the weights associated with the model, only the configuration. Check out the
|
| 104 |
+
[`~PreTrainedModel.from_pretrained`] method to load the model weights.
|
| 105 |
+
"""
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
@add_start_docstrings(
|
| 109 |
+
"The bare Aya Vision Model outputting raw hidden-states without any specific head on top.",
|
| 110 |
+
AYA_VISION_START_DOCSTRING,
|
| 111 |
+
)
|
| 112 |
+
class AyaVisionPreTrainedModel(LlavaPreTrainedModel):
|
| 113 |
+
_supports_quantized_cache = False
|
| 114 |
+
_supports_static_cache = False
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
class AyaVisionCausalLMOutputWithPast(LlavaCausalLMOutputWithPast):
|
| 118 |
+
pass
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
AYA_VISION_INPUTS_DOCSTRING = """
|
| 122 |
+
Args:
|
| 123 |
+
input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
|
| 124 |
+
Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
|
| 125 |
+
it.
|
| 126 |
+
|
| 127 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 128 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 129 |
+
|
| 130 |
+
[What are input IDs?](../glossary#input-ids)
|
| 131 |
+
pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size)):
|
| 132 |
+
The tensors corresponding to the input images. Pixel values can be obtained using
|
| 133 |
+
[`AutoImageProcessor`]. See [`GotOcr2ImageProcessor.__call__`] for details. [`AyaVisionProcessor`] uses
|
| 134 |
+
[`GotOcr2ImageProcessor`] for processing images.
|
| 135 |
+
attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 136 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 137 |
+
|
| 138 |
+
- 1 for tokens that are **not masked**,
|
| 139 |
+
- 0 for tokens that are **masked**.
|
| 140 |
+
|
| 141 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 142 |
+
|
| 143 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 144 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 145 |
+
|
| 146 |
+
If `past_key_values` is used, optionally only the last `decoder_input_ids` have to be input (see
|
| 147 |
+
`past_key_values`).
|
| 148 |
+
|
| 149 |
+
If you want to change padding behavior, you should read [`modeling_opt._prepare_decoder_attention_mask`]
|
| 150 |
+
and modify to your needs. See diagram 1 in [the paper](https://arxiv.org/abs/1910.13461) for more
|
| 151 |
+
information on the default strategy.
|
| 152 |
+
|
| 153 |
+
- 1 indicates the head is **not masked**,
|
| 154 |
+
- 0 indicates the head is **masked**.
|
| 155 |
+
position_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 156 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 157 |
+
config.n_positions - 1]`. [What are position IDs?](../glossary#position-ids)
|
| 158 |
+
past_key_values (`tuple(tuple(torch.FloatTensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
|
| 159 |
+
Tuple of `tuple(torch.FloatTensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape
|
| 160 |
+
`(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape
|
| 161 |
+
`(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.
|
| 162 |
+
|
| 163 |
+
Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention
|
| 164 |
+
blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.
|
| 165 |
+
|
| 166 |
+
If `past_key_values` are used, the user can optionally input only the last `decoder_input_ids` (those that
|
| 167 |
+
don't have their past key value states given to this model) of shape `(batch_size, 1)` instead of all
|
| 168 |
+
`decoder_input_ids` of shape `(batch_size, sequence_length)`.
|
| 169 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
|
| 170 |
+
Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation. This
|
| 171 |
+
is useful if you want more control over how to convert `input_ids` indices into associated vectors than the
|
| 172 |
+
model's internal embedding lookup matrix.
|
| 173 |
+
vision_feature_layer (`Union[int, List[int]], *optional*, defaults to -2`):
|
| 174 |
+
The index of the layer to select the vision feature. If multiple indices are provided,
|
| 175 |
+
the vision feature of the corresponding indices will be concatenated to form the
|
| 176 |
+
vision features.
|
| 177 |
+
vision_feature_select_strategy (`str`, *optional*, defaults to `"default"`):
|
| 178 |
+
The feature selection strategy used to select the vision feature from the vision backbone.
|
| 179 |
+
Can be one of `"default"` or `"full"`.
|
| 180 |
+
use_cache (`bool`, *optional*):
|
| 181 |
+
If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding (see
|
| 182 |
+
`past_key_values`).
|
| 183 |
+
output_attentions (`bool`, *optional*):
|
| 184 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 185 |
+
tensors for more detail.
|
| 186 |
+
output_hidden_states (`bool`, *optional*):
|
| 187 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 188 |
+
more detail.
|
| 189 |
+
return_dict (`bool`, *optional*):
|
| 190 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 191 |
+
cache_position (`torch.LongTensor` of shape `(sequence_length)`, *optional*):
|
| 192 |
+
Indices depicting the position of the input sequence tokens in the sequence. Contrarily to `position_ids`,
|
| 193 |
+
this tensor is not affected by padding. It is used to update the cache in the correct position and to infer
|
| 194 |
+
the complete sequence length.
|
| 195 |
+
"""
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
@add_start_docstrings(
|
| 199 |
+
"""The AyaVision model which consists of a vision backbone and a language model.""",
|
| 200 |
+
AYA_VISION_START_DOCSTRING,
|
| 201 |
+
)
|
| 202 |
+
class AyaVisionForConditionalGeneration(LlavaForConditionalGeneration):
|
| 203 |
+
def tie_weights(self):
|
| 204 |
+
return self.language_model.tie_weights()
|
| 205 |
+
|
| 206 |
+
def resize_token_embeddings(self, new_num_tokens: Optional[int] = None, pad_to_multiple_of=None) -> nn.Embedding:
|
| 207 |
+
model_embeds = self.language_model.resize_token_embeddings(new_num_tokens, pad_to_multiple_of)
|
| 208 |
+
# update vocab size
|
| 209 |
+
self.config.text_config.vocab_size = model_embeds.num_embeddings
|
| 210 |
+
self.vocab_size = model_embeds.num_embeddings
|
| 211 |
+
return model_embeds
|
| 212 |
+
|
| 213 |
+
def forward(
|
| 214 |
+
self,
|
| 215 |
+
input_ids: Optional[torch.LongTensor] = None,
|
| 216 |
+
pixel_values: Optional[torch.FloatTensor] = None,
|
| 217 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 218 |
+
position_ids: Optional[torch.LongTensor] = None,
|
| 219 |
+
past_key_values: Optional[List[torch.FloatTensor]] = None,
|
| 220 |
+
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 221 |
+
vision_feature_layer: Optional[Union[int, List[int]]] = None,
|
| 222 |
+
vision_feature_select_strategy: Optional[str] = None,
|
| 223 |
+
labels: Optional[torch.LongTensor] = None,
|
| 224 |
+
use_cache: Optional[bool] = None,
|
| 225 |
+
output_attentions: Optional[bool] = None,
|
| 226 |
+
output_hidden_states: Optional[bool] = None,
|
| 227 |
+
return_dict: Optional[bool] = None,
|
| 228 |
+
cache_position: Optional[torch.LongTensor] = None,
|
| 229 |
+
logits_to_keep: Union[int, torch.Tensor] = 0,
|
| 230 |
+
image_sizes: Optional[torch.Tensor] = None,
|
| 231 |
+
**lm_kwargs,
|
| 232 |
+
) -> Union[Tuple, AyaVisionCausalLMOutputWithPast]:
|
| 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 |
+
logits_to_keep (`int` or `torch.Tensor`, *optional*):
|
| 240 |
+
If an `int`, compute logits for the last `logits_to_keep` tokens. If `0`, calculate logits for all
|
| 241 |
+
`input_ids` (special case). Only last token logits are needed for generation, and calculating them only for that
|
| 242 |
+
token can save memory, which becomes pretty significant for long sequences or large vocabulary size.
|
| 243 |
+
If a `torch.Tensor`, must be 1D corresponding to the indices to keep in the sequence length dimension.
|
| 244 |
+
This is useful when using packed tensor format (single dimension for batch and sequence length).
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
Returns:
|
| 248 |
+
|
| 249 |
+
Example:
|
| 250 |
+
|
| 251 |
+
```python
|
| 252 |
+
>>> from transformers import AutoProcessor, AyaVisionForConditionalGeneration
|
| 253 |
+
>>> import torch
|
| 254 |
+
|
| 255 |
+
>>> torch_device = "cuda:0"
|
| 256 |
+
>>> processor = AutoProcessor.from_pretrained("CohereForAI/aya-vision-8b", use_fast=True)
|
| 257 |
+
>>> model = AyaVisionForConditionalGeneration.from_pretrained("CohereForAI/aya-vision-8b", device_map=torch_device)
|
| 258 |
+
|
| 259 |
+
>>> messages = [
|
| 260 |
+
... {
|
| 261 |
+
... "role": "user",
|
| 262 |
+
... "content": [
|
| 263 |
+
... {
|
| 264 |
+
... "type": "image",
|
| 265 |
+
... "url": "https://pbs.twimg.com/media/Fx7YvfQWYAIp6rZ?format=jpg&name=medium",
|
| 266 |
+
... },
|
| 267 |
+
... {"type": "text", "text": "चित्र में लिखा पाठ क्या कहता है?"},
|
| 268 |
+
... ],
|
| 269 |
+
... }
|
| 270 |
+
... ]
|
| 271 |
+
|
| 272 |
+
>>> inputs = processor.apply_chat_template(
|
| 273 |
+
... messages, padding=True, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", device=torch_device
|
| 274 |
+
... ).to(model.device)
|
| 275 |
+
|
| 276 |
+
>>> gen_tokens = model.generate(**inputs, max_new_tokens=300, do_sample=True, temperature=0.3)
|
| 277 |
+
>>> processor.tokenizer.decode(gen_tokens[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
|
| 278 |
+
```"""
|
| 279 |
+
super().forward(
|
| 280 |
+
input_ids=input_ids,
|
| 281 |
+
pixel_values=pixel_values,
|
| 282 |
+
attention_mask=attention_mask,
|
| 283 |
+
position_ids=position_ids,
|
| 284 |
+
past_key_values=past_key_values,
|
| 285 |
+
inputs_embeds=inputs_embeds,
|
| 286 |
+
vision_feature_layer=vision_feature_layer,
|
| 287 |
+
vision_feature_select_strategy=vision_feature_select_strategy,
|
| 288 |
+
labels=labels,
|
| 289 |
+
use_cache=use_cache,
|
| 290 |
+
output_attentions=output_attentions,
|
| 291 |
+
output_hidden_states=output_hidden_states,
|
| 292 |
+
return_dict=return_dict,
|
| 293 |
+
cache_position=cache_position,
|
| 294 |
+
logits_to_keep=logits_to_keep,
|
| 295 |
+
image_sizes=image_sizes,
|
| 296 |
+
**lm_kwargs,
|
| 297 |
+
)
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
__all__ = ["AyaVisionForConditionalGeneration", "AyaVisionPreTrainedModel"]
|
lib/python3.12/site-packages/transformers/models/aya_vision/processing_aya_vision.py
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2025 HuggingFace Inc. team. All rights reserved.
|
| 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 |
+
|
| 16 |
+
|
| 17 |
+
from typing import List, Optional, Union
|
| 18 |
+
|
| 19 |
+
from transformers.processing_utils import (
|
| 20 |
+
ImagesKwargs,
|
| 21 |
+
ProcessingKwargs,
|
| 22 |
+
ProcessorMixin,
|
| 23 |
+
Unpack,
|
| 24 |
+
)
|
| 25 |
+
from transformers.tokenization_utils_base import PreTokenizedInput, TextInput
|
| 26 |
+
|
| 27 |
+
from ...image_processing_utils import BatchFeature
|
| 28 |
+
from ...image_utils import (
|
| 29 |
+
ImageInput,
|
| 30 |
+
make_flat_list_of_images,
|
| 31 |
+
)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class AyaVisionImagesKwargs(ImagesKwargs, total=False):
|
| 35 |
+
crop_to_patches: Optional[bool]
|
| 36 |
+
min_patches: Optional[int]
|
| 37 |
+
max_patches: Optional[int]
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
class AyaVisionProcessorKwargs(ProcessingKwargs, total=False):
|
| 41 |
+
images_kwargs: AyaVisionImagesKwargs
|
| 42 |
+
_defaults = {
|
| 43 |
+
"text_kwargs": {
|
| 44 |
+
"padding_side": "left",
|
| 45 |
+
"padding": True,
|
| 46 |
+
},
|
| 47 |
+
"images_kwargs": {
|
| 48 |
+
"crop_to_patches": True,
|
| 49 |
+
},
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
class AyaVisionProcessor(ProcessorMixin):
|
| 54 |
+
r"""
|
| 55 |
+
Constructs a AyaVision processor which wraps a [`AutoImageProcessor`] and
|
| 56 |
+
[`PretrainedTokenizerFast`] tokenizer into a single processor that inherits both the image processor and
|
| 57 |
+
tokenizer functionalities. See the [`~AyaVisionProcessor.__call__`] and [`~AyaVisionProcessor.decode`] for more information.
|
| 58 |
+
Args:
|
| 59 |
+
image_processor ([`AutoImageProcessor`], *optional*):
|
| 60 |
+
The image processor is a required input.
|
| 61 |
+
tokenizer ([`PreTrainedTokenizer`, `PreTrainedTokenizerFast`], *optional*):
|
| 62 |
+
The tokenizer is a required input.
|
| 63 |
+
patch_size (`int`, *optional*, defaults to 28):
|
| 64 |
+
The size of image patches for tokenization.
|
| 65 |
+
img_size (`int`, *optional*, defaults to 364):
|
| 66 |
+
The size of the image to be tokenized. This should correspond to the size given to the image processor.
|
| 67 |
+
image_token (`str`, *optional*, defaults to `"<image>"`):
|
| 68 |
+
The token to be used to represent an image in the text.
|
| 69 |
+
downsample_factor (`int`, *optional*, defaults to 1):
|
| 70 |
+
The factor by which to scale the patch size.
|
| 71 |
+
start_of_img_token (`str`, *optional*, defaults to `"<|START_OF_IMG|>"`):
|
| 72 |
+
The token to be used to represent the start of an image in the text.
|
| 73 |
+
end_of_img_token (`str`, *optional*, defaults to `"<|END_OF_IMG|>"`):
|
| 74 |
+
The token to be used to represent the end of an image in the text.
|
| 75 |
+
img_patch_token (`str`, *optional*, defaults to `"<|IMG_PATCH|>"`):
|
| 76 |
+
The token to be used to represent an image patch in the text.
|
| 77 |
+
img_line_break_token (`str`, *optional*, defaults to `"<|IMG_LINE_BREAK|>"`):
|
| 78 |
+
The token to be used to represent a line break in the text.
|
| 79 |
+
tile_token (`str`, *optional*, defaults to `"TILE"`):
|
| 80 |
+
The token to be used to represent an image patch in the text.
|
| 81 |
+
tile_global_token (`str`, *optional*, defaults to `"TILE_GLOBAL"`):
|
| 82 |
+
The token to be used to represent the cover image in the text.
|
| 83 |
+
chat_template (`str`, *optional*): A Jinja template which will be used to convert lists of messages
|
| 84 |
+
in a chat into a tokenizable string.
|
| 85 |
+
"""
|
| 86 |
+
|
| 87 |
+
attributes = ["image_processor", "tokenizer"]
|
| 88 |
+
valid_kwargs = [
|
| 89 |
+
"chat_template",
|
| 90 |
+
"image_token",
|
| 91 |
+
"patch_size",
|
| 92 |
+
"img_size",
|
| 93 |
+
"downsample_factor",
|
| 94 |
+
"start_of_img_token",
|
| 95 |
+
"end_of_img_token",
|
| 96 |
+
"img_patch_token",
|
| 97 |
+
"img_line_break_token",
|
| 98 |
+
"tile_token",
|
| 99 |
+
"tile_global_token",
|
| 100 |
+
]
|
| 101 |
+
image_processor_class = "AutoImageProcessor"
|
| 102 |
+
tokenizer_class = "AutoTokenizer"
|
| 103 |
+
|
| 104 |
+
def __init__(
|
| 105 |
+
self,
|
| 106 |
+
image_processor=None,
|
| 107 |
+
tokenizer=None,
|
| 108 |
+
patch_size: int = 28,
|
| 109 |
+
img_size: int = 364,
|
| 110 |
+
image_token="<image>", # set the default and let users change if they have peculiar special tokens in rare cases
|
| 111 |
+
downsample_factor: int = 1,
|
| 112 |
+
start_of_img_token="<|START_OF_IMG|>",
|
| 113 |
+
end_of_img_token="<|END_OF_IMG|>",
|
| 114 |
+
img_patch_token="<|IMG_PATCH|>",
|
| 115 |
+
img_line_break_token="<|IMG_LINE_BREAK|>",
|
| 116 |
+
tile_token="TILE",
|
| 117 |
+
tile_global_token="TILE_GLOBAL",
|
| 118 |
+
chat_template=None,
|
| 119 |
+
**kwargs,
|
| 120 |
+
):
|
| 121 |
+
super().__init__(image_processor, tokenizer, chat_template=chat_template)
|
| 122 |
+
|
| 123 |
+
self.image_token = image_token
|
| 124 |
+
self.patch_size = patch_size * downsample_factor
|
| 125 |
+
self.img_size = img_size
|
| 126 |
+
|
| 127 |
+
self.start_of_img_token = start_of_img_token
|
| 128 |
+
self.end_of_img_token = end_of_img_token
|
| 129 |
+
self.img_patch_token = img_patch_token
|
| 130 |
+
self.img_line_break_token = img_line_break_token
|
| 131 |
+
self.tile_token = tile_token
|
| 132 |
+
self.tile_global_token = tile_global_token
|
| 133 |
+
|
| 134 |
+
def _prompt_split_image(self, num_patches):
|
| 135 |
+
"""
|
| 136 |
+
Create a structured string representation of image tokens
|
| 137 |
+
|
| 138 |
+
Args:
|
| 139 |
+
num_patches: Number of patches in the image
|
| 140 |
+
|
| 141 |
+
Returns:
|
| 142 |
+
String with appropriate image tokens
|
| 143 |
+
"""
|
| 144 |
+
|
| 145 |
+
img_patches_per_tile = (self.img_size // self.patch_size) ** 2
|
| 146 |
+
img_string = f"{self.start_of_img_token}"
|
| 147 |
+
if num_patches > 1:
|
| 148 |
+
for idx in range(1, num_patches):
|
| 149 |
+
img_string += f"{self.tile_token}_{idx}" + f"{self.img_patch_token}" * img_patches_per_tile
|
| 150 |
+
|
| 151 |
+
img_string += f"{self.tile_global_token}" + f"{self.img_patch_token}" * img_patches_per_tile
|
| 152 |
+
img_string += f"{self.end_of_img_token}"
|
| 153 |
+
return img_string
|
| 154 |
+
|
| 155 |
+
def __call__(
|
| 156 |
+
self,
|
| 157 |
+
images: Optional[ImageInput] = None,
|
| 158 |
+
text: Optional[Union[TextInput, PreTokenizedInput, List[TextInput], List[PreTokenizedInput]]] = None,
|
| 159 |
+
audio=None,
|
| 160 |
+
videos=None,
|
| 161 |
+
**kwargs: Unpack[AyaVisionProcessorKwargs],
|
| 162 |
+
) -> BatchFeature:
|
| 163 |
+
"""
|
| 164 |
+
Main method to prepare for the model one or several sequences(s) and image(s). This method forwards the `text`
|
| 165 |
+
and `kwargs` arguments to PreTrainedTokenizerFast's [`~PreTrainedTokenizerFast.__call__`] to encode the text.
|
| 166 |
+
To prepare the vision inputs, this method forwards the `images` and `kwargs` arguments to
|
| 167 |
+
GotOcr2ImageProcessor's [`~GotOcr2ImageProcessor.__call__`] if `images` is not `None`.
|
| 168 |
+
|
| 169 |
+
Args:
|
| 170 |
+
images (`PIL.Image.Image`, `np.ndarray`, `torch.Tensor`, `List[PIL.Image.Image]`, `List[np.ndarray]`, `List[torch.Tensor]`):
|
| 171 |
+
The image or batch of images to be prepared. Each image can be a PIL image, NumPy array or PyTorch
|
| 172 |
+
tensor. Both channels-first and channels-last formats are supported.
|
| 173 |
+
text (`str`, `List[str]`, `List[List[str]]`):
|
| 174 |
+
The sequence or batch of sequences to be encoded. Each sequence can be a string or a list of strings
|
| 175 |
+
(pretokenized string). If the sequences are provided as list of strings (pretokenized), you must set
|
| 176 |
+
`is_split_into_words=True` (to lift the ambiguity with a batch of sequences).
|
| 177 |
+
return_tensors (`str` or [`~utils.TensorType`], *optional*):
|
| 178 |
+
If set, will return tensors of a particular framework. Acceptable values are:
|
| 179 |
+
- `'tf'`: Return TensorFlow `tf.constant` objects.
|
| 180 |
+
- `'pt'`: Return PyTorch `torch.Tensor` objects.
|
| 181 |
+
- `'np'`: Return NumPy `np.ndarray` objects.
|
| 182 |
+
- `'jax'`: Return JAX `jnp.ndarray` objects.
|
| 183 |
+
|
| 184 |
+
Returns:
|
| 185 |
+
[`BatchFeature`]: A [`BatchFeature`] with the following fields:
|
| 186 |
+
|
| 187 |
+
- **input_ids** -- List of token ids to be fed to a model. Returned when `text` is not `None`.
|
| 188 |
+
- **attention_mask** -- List of indices specifying which tokens should be attended to by the model (when
|
| 189 |
+
`return_attention_mask=True` or if *"attention_mask"* is in `self.model_input_names` and if `text` is not
|
| 190 |
+
`None`).
|
| 191 |
+
- **pixel_values** -- Pixel values to be fed to a model. Returned when `images` is not `None`.
|
| 192 |
+
"""
|
| 193 |
+
if text is None:
|
| 194 |
+
raise ValueError("You have to specify text.")
|
| 195 |
+
|
| 196 |
+
output_kwargs = self._merge_kwargs(
|
| 197 |
+
AyaVisionProcessorKwargs,
|
| 198 |
+
tokenizer_init_kwargs=self.tokenizer.init_kwargs,
|
| 199 |
+
**kwargs,
|
| 200 |
+
)
|
| 201 |
+
|
| 202 |
+
if not isinstance(text, (list, tuple)):
|
| 203 |
+
text = [text]
|
| 204 |
+
|
| 205 |
+
# Process images
|
| 206 |
+
image_inputs = {}
|
| 207 |
+
if images is not None:
|
| 208 |
+
images = make_flat_list_of_images(images)
|
| 209 |
+
image_inputs = self.image_processor(images=images, **output_kwargs["images_kwargs"])
|
| 210 |
+
num_patches = image_inputs.pop("num_patches")
|
| 211 |
+
image_index = 0
|
| 212 |
+
processed_text = []
|
| 213 |
+
for prompt in text:
|
| 214 |
+
new_prompt = prompt
|
| 215 |
+
while "<image>" in new_prompt:
|
| 216 |
+
# Replace the image placeholder with structured image tokens
|
| 217 |
+
image_tokens = self._prompt_split_image(num_patches[image_index])
|
| 218 |
+
new_prompt = new_prompt.replace("<image>", image_tokens, 1)
|
| 219 |
+
image_index += 1
|
| 220 |
+
processed_text.append(new_prompt)
|
| 221 |
+
|
| 222 |
+
if image_index != len(images):
|
| 223 |
+
raise ValueError("Number of image placeholders in the prompt does not match the number of images.")
|
| 224 |
+
|
| 225 |
+
text = processed_text
|
| 226 |
+
|
| 227 |
+
text_inputs = self.tokenizer(text, **output_kwargs["text_kwargs"])
|
| 228 |
+
|
| 229 |
+
return BatchFeature(data={**text_inputs, **image_inputs})
|
| 230 |
+
|
| 231 |
+
def batch_decode(self, *args, **kwargs):
|
| 232 |
+
"""
|
| 233 |
+
This method forwards all its arguments to PreTrainedTokenizerFast's [`~PreTrainedTokenizer.batch_decode`]. Please
|
| 234 |
+
refer to the docstring of this method for more information.
|
| 235 |
+
"""
|
| 236 |
+
return self.tokenizer.batch_decode(*args, **kwargs)
|
| 237 |
+
|
| 238 |
+
def decode(self, *args, **kwargs):
|
| 239 |
+
"""
|
| 240 |
+
This method forwards all its arguments to PreTrainedTokenizerFast's [`~PreTrainedTokenizer.decode`]. Please refer to
|
| 241 |
+
the docstring of this method for more information.
|
| 242 |
+
"""
|
| 243 |
+
return self.tokenizer.decode(*args, **kwargs)
|
| 244 |
+
|
| 245 |
+
@property
|
| 246 |
+
def model_input_names(self):
|
| 247 |
+
tokenizer_input_names = self.tokenizer.model_input_names
|
| 248 |
+
image_processor_input_names = self.image_processor.model_input_names
|
| 249 |
+
return list(tokenizer_input_names) + list(image_processor_input_names)
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
__all__ = ["AyaVisionProcessor"]
|
lib/python3.12/site-packages/transformers/models/bert_japanese/__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_bert_japanese 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__)
|
lib/python3.12/site-packages/transformers/models/bert_japanese/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (650 Bytes). View file
|
|
|
lib/python3.12/site-packages/transformers/models/bert_japanese/__pycache__/tokenization_bert_japanese.cpython-312.pyc
ADDED
|
Binary file (41.7 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/bert_japanese/tokenization_bert_japanese.py
ADDED
|
@@ -0,0 +1,982 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team.
|
| 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 |
+
"""Tokenization classes."""
|
| 16 |
+
|
| 17 |
+
import collections
|
| 18 |
+
import copy
|
| 19 |
+
import os
|
| 20 |
+
import unicodedata
|
| 21 |
+
from typing import Any, Dict, List, Optional, Tuple
|
| 22 |
+
|
| 23 |
+
from ...tokenization_utils import PreTrainedTokenizer, _is_control, _is_punctuation, _is_whitespace
|
| 24 |
+
from ...utils import is_sentencepiece_available, is_sudachi_projection_available, logging
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
if is_sentencepiece_available():
|
| 28 |
+
import sentencepiece as spm
|
| 29 |
+
else:
|
| 30 |
+
spm = None
|
| 31 |
+
|
| 32 |
+
logger = logging.get_logger(__name__)
|
| 33 |
+
|
| 34 |
+
VOCAB_FILES_NAMES = {"vocab_file": "vocab.txt", "spm_file": "spiece.model"}
|
| 35 |
+
|
| 36 |
+
SPIECE_UNDERLINE = "▁"
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
# Copied from transformers.models.bert.tokenization_bert.load_vocab
|
| 40 |
+
def load_vocab(vocab_file):
|
| 41 |
+
"""Loads a vocabulary file into a dictionary."""
|
| 42 |
+
vocab = collections.OrderedDict()
|
| 43 |
+
with open(vocab_file, "r", encoding="utf-8") as reader:
|
| 44 |
+
tokens = reader.readlines()
|
| 45 |
+
for index, token in enumerate(tokens):
|
| 46 |
+
token = token.rstrip("\n")
|
| 47 |
+
vocab[token] = index
|
| 48 |
+
return vocab
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
# Copied from transformers.models.bert.tokenization_bert.whitespace_tokenize
|
| 52 |
+
def whitespace_tokenize(text):
|
| 53 |
+
"""Runs basic whitespace cleaning and splitting on a piece of text."""
|
| 54 |
+
text = text.strip()
|
| 55 |
+
if not text:
|
| 56 |
+
return []
|
| 57 |
+
tokens = text.split()
|
| 58 |
+
return tokens
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
class BertJapaneseTokenizer(PreTrainedTokenizer):
|
| 62 |
+
r"""
|
| 63 |
+
Construct a BERT tokenizer for Japanese text.
|
| 64 |
+
|
| 65 |
+
This tokenizer inherits from [`PreTrainedTokenizer`] which contains most of the main methods. Users should refer
|
| 66 |
+
to: this superclass for more information regarding those methods.
|
| 67 |
+
|
| 68 |
+
Args:
|
| 69 |
+
vocab_file (`str`):
|
| 70 |
+
Path to a one-wordpiece-per-line vocabulary file.
|
| 71 |
+
spm_file (`str`, *optional*):
|
| 72 |
+
Path to [SentencePiece](https://github.com/google/sentencepiece) file (generally has a .spm or .model
|
| 73 |
+
extension) that contains the vocabulary.
|
| 74 |
+
do_lower_case (`bool`, *optional*, defaults to `True`):
|
| 75 |
+
Whether to lower case the input. Only has an effect when do_basic_tokenize=True.
|
| 76 |
+
do_word_tokenize (`bool`, *optional*, defaults to `True`):
|
| 77 |
+
Whether to do word tokenization.
|
| 78 |
+
do_subword_tokenize (`bool`, *optional*, defaults to `True`):
|
| 79 |
+
Whether to do subword tokenization.
|
| 80 |
+
word_tokenizer_type (`str`, *optional*, defaults to `"basic"`):
|
| 81 |
+
Type of word tokenizer. Choose from ["basic", "mecab", "sudachi", "jumanpp"].
|
| 82 |
+
subword_tokenizer_type (`str`, *optional*, defaults to `"wordpiece"`):
|
| 83 |
+
Type of subword tokenizer. Choose from ["wordpiece", "character", "sentencepiece",].
|
| 84 |
+
mecab_kwargs (`dict`, *optional*):
|
| 85 |
+
Dictionary passed to the `MecabTokenizer` constructor.
|
| 86 |
+
sudachi_kwargs (`dict`, *optional*):
|
| 87 |
+
Dictionary passed to the `SudachiTokenizer` constructor.
|
| 88 |
+
jumanpp_kwargs (`dict`, *optional*):
|
| 89 |
+
Dictionary passed to the `JumanppTokenizer` constructor.
|
| 90 |
+
"""
|
| 91 |
+
|
| 92 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 93 |
+
|
| 94 |
+
def __init__(
|
| 95 |
+
self,
|
| 96 |
+
vocab_file,
|
| 97 |
+
spm_file=None,
|
| 98 |
+
do_lower_case=False,
|
| 99 |
+
do_word_tokenize=True,
|
| 100 |
+
do_subword_tokenize=True,
|
| 101 |
+
word_tokenizer_type="basic",
|
| 102 |
+
subword_tokenizer_type="wordpiece",
|
| 103 |
+
never_split=None,
|
| 104 |
+
unk_token="[UNK]",
|
| 105 |
+
sep_token="[SEP]",
|
| 106 |
+
pad_token="[PAD]",
|
| 107 |
+
cls_token="[CLS]",
|
| 108 |
+
mask_token="[MASK]",
|
| 109 |
+
mecab_kwargs=None,
|
| 110 |
+
sudachi_kwargs=None,
|
| 111 |
+
jumanpp_kwargs=None,
|
| 112 |
+
**kwargs,
|
| 113 |
+
):
|
| 114 |
+
if subword_tokenizer_type == "sentencepiece":
|
| 115 |
+
if not os.path.isfile(spm_file):
|
| 116 |
+
raise ValueError(
|
| 117 |
+
f"Can't find a vocabulary file at path '{spm_file}'. To load the vocabulary from a Google"
|
| 118 |
+
" pretrained model use `tokenizer = AutoTokenizer.from_pretrained(PRETRAINED_MODEL_NAME)`"
|
| 119 |
+
)
|
| 120 |
+
self.spm_file = spm_file
|
| 121 |
+
else:
|
| 122 |
+
if not os.path.isfile(vocab_file):
|
| 123 |
+
raise ValueError(
|
| 124 |
+
f"Can't find a vocabulary file at path '{vocab_file}'. To load the vocabulary from a Google"
|
| 125 |
+
" pretrained model use `tokenizer = AutoTokenizer.from_pretrained(PRETRAINED_MODEL_NAME)`"
|
| 126 |
+
)
|
| 127 |
+
self.vocab = load_vocab(vocab_file)
|
| 128 |
+
self.ids_to_tokens = collections.OrderedDict([(ids, tok) for tok, ids in self.vocab.items()])
|
| 129 |
+
|
| 130 |
+
self.do_word_tokenize = do_word_tokenize
|
| 131 |
+
self.word_tokenizer_type = word_tokenizer_type
|
| 132 |
+
self.lower_case = do_lower_case
|
| 133 |
+
self.never_split = never_split
|
| 134 |
+
self.mecab_kwargs = copy.deepcopy(mecab_kwargs)
|
| 135 |
+
self.sudachi_kwargs = copy.deepcopy(sudachi_kwargs)
|
| 136 |
+
self.jumanpp_kwargs = copy.deepcopy(jumanpp_kwargs)
|
| 137 |
+
if do_word_tokenize:
|
| 138 |
+
if word_tokenizer_type == "basic":
|
| 139 |
+
self.word_tokenizer = BasicTokenizer(
|
| 140 |
+
do_lower_case=do_lower_case, never_split=never_split, tokenize_chinese_chars=False
|
| 141 |
+
)
|
| 142 |
+
elif word_tokenizer_type == "mecab":
|
| 143 |
+
self.word_tokenizer = MecabTokenizer(
|
| 144 |
+
do_lower_case=do_lower_case, never_split=never_split, **(mecab_kwargs or {})
|
| 145 |
+
)
|
| 146 |
+
elif word_tokenizer_type == "sudachi":
|
| 147 |
+
self.word_tokenizer = SudachiTokenizer(
|
| 148 |
+
do_lower_case=do_lower_case, never_split=never_split, **(sudachi_kwargs or {})
|
| 149 |
+
)
|
| 150 |
+
elif word_tokenizer_type == "jumanpp":
|
| 151 |
+
self.word_tokenizer = JumanppTokenizer(
|
| 152 |
+
do_lower_case=do_lower_case, never_split=never_split, **(jumanpp_kwargs or {})
|
| 153 |
+
)
|
| 154 |
+
else:
|
| 155 |
+
raise ValueError(f"Invalid word_tokenizer_type '{word_tokenizer_type}' is specified.")
|
| 156 |
+
|
| 157 |
+
self.do_subword_tokenize = do_subword_tokenize
|
| 158 |
+
self.subword_tokenizer_type = subword_tokenizer_type
|
| 159 |
+
if do_subword_tokenize:
|
| 160 |
+
if subword_tokenizer_type == "wordpiece":
|
| 161 |
+
self.subword_tokenizer = WordpieceTokenizer(vocab=self.vocab, unk_token=str(unk_token))
|
| 162 |
+
elif subword_tokenizer_type == "character":
|
| 163 |
+
self.subword_tokenizer = CharacterTokenizer(vocab=self.vocab, unk_token=str(unk_token))
|
| 164 |
+
elif subword_tokenizer_type == "sentencepiece":
|
| 165 |
+
self.subword_tokenizer = SentencepieceTokenizer(vocab=self.spm_file, unk_token=str(unk_token))
|
| 166 |
+
else:
|
| 167 |
+
raise ValueError(f"Invalid subword_tokenizer_type '{subword_tokenizer_type}' is specified.")
|
| 168 |
+
super().__init__(
|
| 169 |
+
spm_file=spm_file,
|
| 170 |
+
unk_token=unk_token,
|
| 171 |
+
sep_token=sep_token,
|
| 172 |
+
pad_token=pad_token,
|
| 173 |
+
cls_token=cls_token,
|
| 174 |
+
mask_token=mask_token,
|
| 175 |
+
do_lower_case=do_lower_case,
|
| 176 |
+
do_word_tokenize=do_word_tokenize,
|
| 177 |
+
do_subword_tokenize=do_subword_tokenize,
|
| 178 |
+
word_tokenizer_type=word_tokenizer_type,
|
| 179 |
+
subword_tokenizer_type=subword_tokenizer_type,
|
| 180 |
+
never_split=never_split,
|
| 181 |
+
mecab_kwargs=mecab_kwargs,
|
| 182 |
+
sudachi_kwargs=sudachi_kwargs,
|
| 183 |
+
jumanpp_kwargs=jumanpp_kwargs,
|
| 184 |
+
**kwargs,
|
| 185 |
+
)
|
| 186 |
+
|
| 187 |
+
@property
|
| 188 |
+
def do_lower_case(self):
|
| 189 |
+
return self.lower_case
|
| 190 |
+
|
| 191 |
+
def __getstate__(self):
|
| 192 |
+
state = dict(self.__dict__)
|
| 193 |
+
if self.word_tokenizer_type in ["mecab", "sudachi", "jumanpp"]:
|
| 194 |
+
del state["word_tokenizer"]
|
| 195 |
+
return state
|
| 196 |
+
|
| 197 |
+
def __setstate__(self, state):
|
| 198 |
+
self.__dict__ = state
|
| 199 |
+
if self.word_tokenizer_type == "mecab":
|
| 200 |
+
self.word_tokenizer = MecabTokenizer(
|
| 201 |
+
do_lower_case=self.do_lower_case, never_split=self.never_split, **(self.mecab_kwargs or {})
|
| 202 |
+
)
|
| 203 |
+
elif self.word_tokenizer_type == "sudachi":
|
| 204 |
+
self.word_tokenizer = SudachiTokenizer(
|
| 205 |
+
do_lower_case=self.do_lower_case, never_split=self.never_split, **(self.sudachi_kwargs or {})
|
| 206 |
+
)
|
| 207 |
+
elif self.word_tokenizer_type == "jumanpp":
|
| 208 |
+
self.word_tokenizer = JumanppTokenizer(
|
| 209 |
+
do_lower_case=self.do_lower_case, never_split=self.never_split, **(self.jumanpp_kwargs or {})
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
def _tokenize(self, text):
|
| 213 |
+
if self.do_word_tokenize:
|
| 214 |
+
tokens = self.word_tokenizer.tokenize(text, never_split=self.all_special_tokens)
|
| 215 |
+
else:
|
| 216 |
+
tokens = [text]
|
| 217 |
+
|
| 218 |
+
if self.do_subword_tokenize:
|
| 219 |
+
split_tokens = [sub_token for token in tokens for sub_token in self.subword_tokenizer.tokenize(token)]
|
| 220 |
+
else:
|
| 221 |
+
split_tokens = tokens
|
| 222 |
+
|
| 223 |
+
return split_tokens
|
| 224 |
+
|
| 225 |
+
@property
|
| 226 |
+
def vocab_size(self):
|
| 227 |
+
if self.subword_tokenizer_type == "sentencepiece":
|
| 228 |
+
return len(self.subword_tokenizer.sp_model)
|
| 229 |
+
return len(self.vocab)
|
| 230 |
+
|
| 231 |
+
def get_vocab(self):
|
| 232 |
+
if self.subword_tokenizer_type == "sentencepiece":
|
| 233 |
+
vocab = {self.convert_ids_to_tokens(i): i for i in range(self.vocab_size)}
|
| 234 |
+
vocab.update(self.added_tokens_encoder)
|
| 235 |
+
return vocab
|
| 236 |
+
return dict(self.vocab, **self.added_tokens_encoder)
|
| 237 |
+
|
| 238 |
+
def _convert_token_to_id(self, token):
|
| 239 |
+
"""Converts a token (str) in an id using the vocab."""
|
| 240 |
+
if self.subword_tokenizer_type == "sentencepiece":
|
| 241 |
+
return self.subword_tokenizer.sp_model.PieceToId(token)
|
| 242 |
+
return self.vocab.get(token, self.vocab.get(self.unk_token))
|
| 243 |
+
|
| 244 |
+
def _convert_id_to_token(self, index):
|
| 245 |
+
"""Converts an index (integer) in a token (str) using the vocab."""
|
| 246 |
+
if self.subword_tokenizer_type == "sentencepiece":
|
| 247 |
+
return self.subword_tokenizer.sp_model.IdToPiece(index)
|
| 248 |
+
return self.ids_to_tokens.get(index, self.unk_token)
|
| 249 |
+
|
| 250 |
+
def convert_tokens_to_string(self, tokens):
|
| 251 |
+
"""Converts a sequence of tokens (string) in a single string."""
|
| 252 |
+
if self.subword_tokenizer_type == "sentencepiece":
|
| 253 |
+
return self.subword_tokenizer.sp_model.decode(tokens)
|
| 254 |
+
out_string = " ".join(tokens).replace(" ##", "").strip()
|
| 255 |
+
return out_string
|
| 256 |
+
|
| 257 |
+
# Copied from transformers.models.bert.tokenization_bert.BertTokenizer.build_inputs_with_special_tokens
|
| 258 |
+
def build_inputs_with_special_tokens(
|
| 259 |
+
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
| 260 |
+
) -> List[int]:
|
| 261 |
+
"""
|
| 262 |
+
Build model inputs from a sequence or a pair of sequence for sequence classification tasks by concatenating and
|
| 263 |
+
adding special tokens. A BERT sequence has the following format:
|
| 264 |
+
|
| 265 |
+
- single sequence: `[CLS] X [SEP]`
|
| 266 |
+
- pair of sequences: `[CLS] A [SEP] B [SEP]`
|
| 267 |
+
|
| 268 |
+
Args:
|
| 269 |
+
token_ids_0 (`List[int]`):
|
| 270 |
+
List of IDs to which the special tokens will be added.
|
| 271 |
+
token_ids_1 (`List[int]`, *optional*):
|
| 272 |
+
Optional second list of IDs for sequence pairs.
|
| 273 |
+
|
| 274 |
+
Returns:
|
| 275 |
+
`List[int]`: List of [input IDs](../glossary#input-ids) with the appropriate special tokens.
|
| 276 |
+
"""
|
| 277 |
+
if token_ids_1 is None:
|
| 278 |
+
return [self.cls_token_id] + token_ids_0 + [self.sep_token_id]
|
| 279 |
+
cls = [self.cls_token_id]
|
| 280 |
+
sep = [self.sep_token_id]
|
| 281 |
+
return cls + token_ids_0 + sep + token_ids_1 + sep
|
| 282 |
+
|
| 283 |
+
# Copied from transformers.models.bert.tokenization_bert.BertTokenizer.get_special_tokens_mask
|
| 284 |
+
def get_special_tokens_mask(
|
| 285 |
+
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None, already_has_special_tokens: bool = False
|
| 286 |
+
) -> List[int]:
|
| 287 |
+
"""
|
| 288 |
+
Retrieve sequence ids from a token list that has no special tokens added. This method is called when adding
|
| 289 |
+
special tokens using the tokenizer `prepare_for_model` method.
|
| 290 |
+
|
| 291 |
+
Args:
|
| 292 |
+
token_ids_0 (`List[int]`):
|
| 293 |
+
List of IDs.
|
| 294 |
+
token_ids_1 (`List[int]`, *optional*):
|
| 295 |
+
Optional second list of IDs for sequence pairs.
|
| 296 |
+
already_has_special_tokens (`bool`, *optional*, defaults to `False`):
|
| 297 |
+
Whether or not the token list is already formatted with special tokens for the model.
|
| 298 |
+
|
| 299 |
+
Returns:
|
| 300 |
+
`List[int]`: A list of integers in the range [0, 1]: 1 for a special token, 0 for a sequence token.
|
| 301 |
+
"""
|
| 302 |
+
|
| 303 |
+
if already_has_special_tokens:
|
| 304 |
+
return super().get_special_tokens_mask(
|
| 305 |
+
token_ids_0=token_ids_0, token_ids_1=token_ids_1, already_has_special_tokens=True
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
if token_ids_1 is not None:
|
| 309 |
+
return [1] + ([0] * len(token_ids_0)) + [1] + ([0] * len(token_ids_1)) + [1]
|
| 310 |
+
return [1] + ([0] * len(token_ids_0)) + [1]
|
| 311 |
+
|
| 312 |
+
# Copied from transformers.models.bert.tokenization_bert.BertTokenizer.create_token_type_ids_from_sequences
|
| 313 |
+
def create_token_type_ids_from_sequences(
|
| 314 |
+
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
| 315 |
+
) -> List[int]:
|
| 316 |
+
"""
|
| 317 |
+
Create a mask from the two sequences passed to be used in a sequence-pair classification task. A BERT sequence
|
| 318 |
+
pair mask has the following format:
|
| 319 |
+
|
| 320 |
+
```
|
| 321 |
+
0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
|
| 322 |
+
| first sequence | second sequence |
|
| 323 |
+
```
|
| 324 |
+
|
| 325 |
+
If `token_ids_1` is `None`, this method only returns the first portion of the mask (0s).
|
| 326 |
+
|
| 327 |
+
Args:
|
| 328 |
+
token_ids_0 (`List[int]`):
|
| 329 |
+
List of IDs.
|
| 330 |
+
token_ids_1 (`List[int]`, *optional*):
|
| 331 |
+
Optional second list of IDs for sequence pairs.
|
| 332 |
+
|
| 333 |
+
Returns:
|
| 334 |
+
`List[int]`: List of [token type IDs](../glossary#token-type-ids) according to the given sequence(s).
|
| 335 |
+
"""
|
| 336 |
+
sep = [self.sep_token_id]
|
| 337 |
+
cls = [self.cls_token_id]
|
| 338 |
+
if token_ids_1 is None:
|
| 339 |
+
return len(cls + token_ids_0 + sep) * [0]
|
| 340 |
+
return len(cls + token_ids_0 + sep) * [0] + len(token_ids_1 + sep) * [1]
|
| 341 |
+
|
| 342 |
+
def save_vocabulary(self, save_directory: str, filename_prefix: Optional[str] = None) -> Tuple[str]:
|
| 343 |
+
if os.path.isdir(save_directory):
|
| 344 |
+
if self.subword_tokenizer_type == "sentencepiece":
|
| 345 |
+
vocab_file = os.path.join(
|
| 346 |
+
save_directory, (filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["spm_file"]
|
| 347 |
+
)
|
| 348 |
+
else:
|
| 349 |
+
vocab_file = os.path.join(
|
| 350 |
+
save_directory,
|
| 351 |
+
(filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["vocab_file"],
|
| 352 |
+
)
|
| 353 |
+
else:
|
| 354 |
+
vocab_file = (filename_prefix + "-" if filename_prefix else "") + save_directory
|
| 355 |
+
|
| 356 |
+
if self.subword_tokenizer_type == "sentencepiece":
|
| 357 |
+
with open(vocab_file, "wb") as writer:
|
| 358 |
+
content_spiece_model = self.subword_tokenizer.sp_model.serialized_model_proto()
|
| 359 |
+
writer.write(content_spiece_model)
|
| 360 |
+
else:
|
| 361 |
+
with open(vocab_file, "w", encoding="utf-8") as writer:
|
| 362 |
+
index = 0
|
| 363 |
+
for token, token_index in sorted(self.vocab.items(), key=lambda kv: kv[1]):
|
| 364 |
+
if index != token_index:
|
| 365 |
+
logger.warning(
|
| 366 |
+
f"Saving vocabulary to {vocab_file}: vocabulary indices are not consecutive."
|
| 367 |
+
" Please check that the vocabulary is not corrupted!"
|
| 368 |
+
)
|
| 369 |
+
index = token_index
|
| 370 |
+
writer.write(token + "\n")
|
| 371 |
+
index += 1
|
| 372 |
+
return (vocab_file,)
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
class MecabTokenizer:
|
| 376 |
+
"""Runs basic tokenization with MeCab morphological parser."""
|
| 377 |
+
|
| 378 |
+
def __init__(
|
| 379 |
+
self,
|
| 380 |
+
do_lower_case=False,
|
| 381 |
+
never_split=None,
|
| 382 |
+
normalize_text=True,
|
| 383 |
+
mecab_dic: Optional[str] = "unidic_lite",
|
| 384 |
+
mecab_option: Optional[str] = None,
|
| 385 |
+
):
|
| 386 |
+
"""
|
| 387 |
+
Constructs a MecabTokenizer.
|
| 388 |
+
|
| 389 |
+
Args:
|
| 390 |
+
**do_lower_case**: (*optional*) boolean (default True)
|
| 391 |
+
Whether to lowercase the input.
|
| 392 |
+
**never_split**: (*optional*) list of str
|
| 393 |
+
Kept for backward compatibility purposes. Now implemented directly at the base class level (see
|
| 394 |
+
[`PreTrainedTokenizer.tokenize`]) List of tokens not to split.
|
| 395 |
+
**normalize_text**: (*optional*) boolean (default True)
|
| 396 |
+
Whether to apply unicode normalization to text before tokenization.
|
| 397 |
+
**mecab_dic**: (*optional*) string (default "ipadic")
|
| 398 |
+
Name of dictionary to be used for MeCab initialization. If you are using a system-installed dictionary,
|
| 399 |
+
set this option to `None` and modify *mecab_option*.
|
| 400 |
+
**mecab_option**: (*optional*) string
|
| 401 |
+
String passed to MeCab constructor.
|
| 402 |
+
"""
|
| 403 |
+
self.do_lower_case = do_lower_case
|
| 404 |
+
self.never_split = never_split if never_split is not None else []
|
| 405 |
+
self.normalize_text = normalize_text
|
| 406 |
+
|
| 407 |
+
try:
|
| 408 |
+
import fugashi
|
| 409 |
+
except ModuleNotFoundError as error:
|
| 410 |
+
raise error.__class__(
|
| 411 |
+
"You need to install fugashi to use MecabTokenizer. "
|
| 412 |
+
"See https://pypi.org/project/fugashi/ for installation."
|
| 413 |
+
)
|
| 414 |
+
|
| 415 |
+
mecab_option = mecab_option or ""
|
| 416 |
+
|
| 417 |
+
if mecab_dic is not None:
|
| 418 |
+
if mecab_dic == "ipadic":
|
| 419 |
+
try:
|
| 420 |
+
import ipadic
|
| 421 |
+
except ModuleNotFoundError as error:
|
| 422 |
+
raise error.__class__(
|
| 423 |
+
"The ipadic dictionary is not installed. "
|
| 424 |
+
"See https://github.com/polm/ipadic-py for installation."
|
| 425 |
+
)
|
| 426 |
+
|
| 427 |
+
dic_dir = ipadic.DICDIR
|
| 428 |
+
|
| 429 |
+
elif mecab_dic == "unidic_lite":
|
| 430 |
+
try:
|
| 431 |
+
import unidic_lite
|
| 432 |
+
except ModuleNotFoundError as error:
|
| 433 |
+
raise error.__class__(
|
| 434 |
+
"The unidic_lite dictionary is not installed. "
|
| 435 |
+
"See https://github.com/polm/unidic-lite for installation."
|
| 436 |
+
)
|
| 437 |
+
|
| 438 |
+
dic_dir = unidic_lite.DICDIR
|
| 439 |
+
|
| 440 |
+
elif mecab_dic == "unidic":
|
| 441 |
+
try:
|
| 442 |
+
import unidic
|
| 443 |
+
except ModuleNotFoundError as error:
|
| 444 |
+
raise error.__class__(
|
| 445 |
+
"The unidic dictionary is not installed. "
|
| 446 |
+
"See https://github.com/polm/unidic-py for installation."
|
| 447 |
+
)
|
| 448 |
+
|
| 449 |
+
dic_dir = unidic.DICDIR
|
| 450 |
+
if not os.path.isdir(dic_dir):
|
| 451 |
+
raise RuntimeError(
|
| 452 |
+
"The unidic dictionary itself is not found. "
|
| 453 |
+
"See https://github.com/polm/unidic-py for installation."
|
| 454 |
+
)
|
| 455 |
+
|
| 456 |
+
else:
|
| 457 |
+
raise ValueError("Invalid mecab_dic is specified.")
|
| 458 |
+
|
| 459 |
+
mecabrc = os.path.join(dic_dir, "mecabrc")
|
| 460 |
+
mecab_option = f'-d "{dic_dir}" -r "{mecabrc}" ' + mecab_option
|
| 461 |
+
|
| 462 |
+
self.mecab = fugashi.GenericTagger(mecab_option)
|
| 463 |
+
|
| 464 |
+
def tokenize(self, text, never_split=None, **kwargs):
|
| 465 |
+
"""Tokenizes a piece of text."""
|
| 466 |
+
if self.normalize_text:
|
| 467 |
+
text = unicodedata.normalize("NFKC", text)
|
| 468 |
+
|
| 469 |
+
never_split = self.never_split + (never_split if never_split is not None else [])
|
| 470 |
+
tokens = []
|
| 471 |
+
|
| 472 |
+
for word in self.mecab(text):
|
| 473 |
+
token = word.surface
|
| 474 |
+
|
| 475 |
+
if self.do_lower_case and token not in never_split:
|
| 476 |
+
token = token.lower()
|
| 477 |
+
|
| 478 |
+
tokens.append(token)
|
| 479 |
+
|
| 480 |
+
return tokens
|
| 481 |
+
|
| 482 |
+
|
| 483 |
+
class SudachiTokenizer:
|
| 484 |
+
"""Runs basic tokenization with Sudachi morphological parser."""
|
| 485 |
+
|
| 486 |
+
def __init__(
|
| 487 |
+
self,
|
| 488 |
+
do_lower_case=False,
|
| 489 |
+
never_split=None,
|
| 490 |
+
normalize_text=True,
|
| 491 |
+
trim_whitespace=False,
|
| 492 |
+
sudachi_split_mode="A",
|
| 493 |
+
sudachi_config_path=None,
|
| 494 |
+
sudachi_resource_dir=None,
|
| 495 |
+
sudachi_dict_type="core",
|
| 496 |
+
sudachi_projection=None,
|
| 497 |
+
):
|
| 498 |
+
"""
|
| 499 |
+
Constructs a SudachiTokenizer.
|
| 500 |
+
|
| 501 |
+
Args:
|
| 502 |
+
**do_lower_case**: (*optional*) boolean (default True)
|
| 503 |
+
Whether to lowercase the input.
|
| 504 |
+
**never_split**: (*optional*) list of str
|
| 505 |
+
Kept for backward compatibility purposes. Now implemented directly at the base class level (see
|
| 506 |
+
[`PreTrainedTokenizer.tokenize`]) List of tokens not to split.
|
| 507 |
+
**normalize_text**: (*optional*) boolean (default True)
|
| 508 |
+
Whether to apply unicode normalization to text before tokenization.
|
| 509 |
+
**trim_whitespace**: (*optional*) boolean (default False)
|
| 510 |
+
Whether to trim all whitespace, tab, newline from tokens.
|
| 511 |
+
**sudachi_split_mode**: (*optional*) string
|
| 512 |
+
Split mode of sudachi, choose from `["A", "B", "C"]`.
|
| 513 |
+
**sudachi_config_path**: (*optional*) string
|
| 514 |
+
**sudachi_resource_dir**: (*optional*) string
|
| 515 |
+
**sudachi_dict_type**: (*optional*) string
|
| 516 |
+
dict type of sudachi, choose from `["small", "core", "full"]`.
|
| 517 |
+
**sudachi_projection**: (*optional*) string
|
| 518 |
+
Word projection mode of sudachi, choose from `["surface", "normalized", "reading", "dictionary", "dictionary_and_surface", "normalized_and_surface", "normalized_nouns"]`.
|
| 519 |
+
"""
|
| 520 |
+
|
| 521 |
+
self.do_lower_case = do_lower_case
|
| 522 |
+
self.never_split = never_split if never_split is not None else []
|
| 523 |
+
self.normalize_text = normalize_text
|
| 524 |
+
self.trim_whitespace = trim_whitespace
|
| 525 |
+
|
| 526 |
+
try:
|
| 527 |
+
from sudachipy import dictionary, tokenizer
|
| 528 |
+
except ImportError:
|
| 529 |
+
raise ImportError(
|
| 530 |
+
"You need to install sudachipy to use SudachiTokenizer. "
|
| 531 |
+
"See https://github.com/WorksApplications/SudachiPy for installation."
|
| 532 |
+
)
|
| 533 |
+
|
| 534 |
+
if sudachi_split_mode == "A":
|
| 535 |
+
self.split_mode = tokenizer.Tokenizer.SplitMode.A
|
| 536 |
+
elif sudachi_split_mode == "B":
|
| 537 |
+
self.split_mode = tokenizer.Tokenizer.SplitMode.B
|
| 538 |
+
elif sudachi_split_mode == "C":
|
| 539 |
+
self.split_mode = tokenizer.Tokenizer.SplitMode.C
|
| 540 |
+
else:
|
| 541 |
+
raise ValueError("Invalid sudachi_split_mode is specified.")
|
| 542 |
+
|
| 543 |
+
self.projection = sudachi_projection
|
| 544 |
+
|
| 545 |
+
sudachi_dictionary = dictionary.Dictionary(
|
| 546 |
+
config_path=sudachi_config_path, resource_dir=sudachi_resource_dir, dict=sudachi_dict_type
|
| 547 |
+
)
|
| 548 |
+
if is_sudachi_projection_available():
|
| 549 |
+
self.sudachi = sudachi_dictionary.create(self.split_mode, projection=self.projection)
|
| 550 |
+
elif self.projection is not None:
|
| 551 |
+
raise ImportError("You need to install sudachipy>=0.6.8 to specify `projection` field in sudachi_kwargs.")
|
| 552 |
+
else:
|
| 553 |
+
self.sudachi = sudachi_dictionary.create(self.split_mode)
|
| 554 |
+
|
| 555 |
+
def tokenize(self, text, never_split=None, **kwargs):
|
| 556 |
+
"""Tokenizes a piece of text."""
|
| 557 |
+
if self.normalize_text:
|
| 558 |
+
text = unicodedata.normalize("NFKC", text)
|
| 559 |
+
|
| 560 |
+
never_split = self.never_split + (never_split if never_split is not None else [])
|
| 561 |
+
tokens = []
|
| 562 |
+
|
| 563 |
+
for word in self.sudachi.tokenize(text):
|
| 564 |
+
token = word.surface()
|
| 565 |
+
|
| 566 |
+
if self.do_lower_case and token not in never_split:
|
| 567 |
+
token = token.lower()
|
| 568 |
+
|
| 569 |
+
if self.trim_whitespace:
|
| 570 |
+
if token.strip() == "":
|
| 571 |
+
continue
|
| 572 |
+
else:
|
| 573 |
+
token = token.strip()
|
| 574 |
+
|
| 575 |
+
tokens.append(token)
|
| 576 |
+
|
| 577 |
+
return tokens
|
| 578 |
+
|
| 579 |
+
|
| 580 |
+
class JumanppTokenizer:
|
| 581 |
+
"""Runs basic tokenization with jumanpp morphological parser."""
|
| 582 |
+
|
| 583 |
+
def __init__(
|
| 584 |
+
self,
|
| 585 |
+
do_lower_case=False,
|
| 586 |
+
never_split=None,
|
| 587 |
+
normalize_text=True,
|
| 588 |
+
trim_whitespace=False,
|
| 589 |
+
):
|
| 590 |
+
"""
|
| 591 |
+
Constructs a JumanppTokenizer.
|
| 592 |
+
|
| 593 |
+
Args:
|
| 594 |
+
**do_lower_case**: (*optional*) boolean (default True)
|
| 595 |
+
Whether to lowercase the input.
|
| 596 |
+
**never_split**: (*optional*) list of str
|
| 597 |
+
Kept for backward compatibility purposes. Now implemented directly at the base class level (see
|
| 598 |
+
[`PreTrainedTokenizer.tokenize`]) List of tokens not to split.
|
| 599 |
+
**normalize_text**: (*optional*) boolean (default True)
|
| 600 |
+
Whether to apply unicode normalization to text before tokenization.
|
| 601 |
+
**trim_whitespace**: (*optional*) boolean (default False)
|
| 602 |
+
Whether to trim all whitespace, tab, newline from tokens.
|
| 603 |
+
"""
|
| 604 |
+
|
| 605 |
+
self.do_lower_case = do_lower_case
|
| 606 |
+
self.never_split = never_split if never_split is not None else []
|
| 607 |
+
self.normalize_text = normalize_text
|
| 608 |
+
self.trim_whitespace = trim_whitespace
|
| 609 |
+
|
| 610 |
+
try:
|
| 611 |
+
import rhoknp
|
| 612 |
+
except ImportError:
|
| 613 |
+
raise ImportError(
|
| 614 |
+
"You need to install rhoknp to use JumanppTokenizer. "
|
| 615 |
+
"See https://github.com/ku-nlp/rhoknp for installation."
|
| 616 |
+
)
|
| 617 |
+
|
| 618 |
+
self.juman = rhoknp.Jumanpp()
|
| 619 |
+
|
| 620 |
+
def tokenize(self, text, never_split=None, **kwargs):
|
| 621 |
+
"""Tokenizes a piece of text."""
|
| 622 |
+
if self.normalize_text:
|
| 623 |
+
text = unicodedata.normalize("NFKC", text)
|
| 624 |
+
|
| 625 |
+
text = text.strip()
|
| 626 |
+
|
| 627 |
+
never_split = self.never_split + (never_split if never_split is not None else [])
|
| 628 |
+
tokens = []
|
| 629 |
+
|
| 630 |
+
for mrph in self.juman.apply_to_sentence(text).morphemes:
|
| 631 |
+
token = mrph.text
|
| 632 |
+
|
| 633 |
+
if self.do_lower_case and token not in never_split:
|
| 634 |
+
token = token.lower()
|
| 635 |
+
|
| 636 |
+
if self.trim_whitespace:
|
| 637 |
+
if token.strip() == "":
|
| 638 |
+
continue
|
| 639 |
+
else:
|
| 640 |
+
token = token.strip()
|
| 641 |
+
|
| 642 |
+
tokens.append(token)
|
| 643 |
+
|
| 644 |
+
return tokens
|
| 645 |
+
|
| 646 |
+
|
| 647 |
+
class CharacterTokenizer:
|
| 648 |
+
"""Runs Character tokenization."""
|
| 649 |
+
|
| 650 |
+
def __init__(self, vocab, unk_token, normalize_text=True):
|
| 651 |
+
"""
|
| 652 |
+
Constructs a CharacterTokenizer.
|
| 653 |
+
|
| 654 |
+
Args:
|
| 655 |
+
**vocab**:
|
| 656 |
+
Vocabulary object.
|
| 657 |
+
**unk_token**: str
|
| 658 |
+
A special symbol for out-of-vocabulary token.
|
| 659 |
+
**normalize_text**: (`optional`) boolean (default True)
|
| 660 |
+
Whether to apply unicode normalization to text before tokenization.
|
| 661 |
+
"""
|
| 662 |
+
self.vocab = vocab
|
| 663 |
+
self.unk_token = unk_token
|
| 664 |
+
self.normalize_text = normalize_text
|
| 665 |
+
|
| 666 |
+
def tokenize(self, text):
|
| 667 |
+
"""
|
| 668 |
+
Tokenizes a piece of text into characters.
|
| 669 |
+
|
| 670 |
+
For example, `input = "apple""` wil return as output `["a", "p", "p", "l", "e"]`.
|
| 671 |
+
|
| 672 |
+
Args:
|
| 673 |
+
text: A single token or whitespace separated tokens.
|
| 674 |
+
This should have already been passed through *BasicTokenizer*.
|
| 675 |
+
|
| 676 |
+
Returns:
|
| 677 |
+
A list of characters.
|
| 678 |
+
"""
|
| 679 |
+
if self.normalize_text:
|
| 680 |
+
text = unicodedata.normalize("NFKC", text)
|
| 681 |
+
|
| 682 |
+
output_tokens = []
|
| 683 |
+
for char in text:
|
| 684 |
+
if char not in self.vocab:
|
| 685 |
+
output_tokens.append(self.unk_token)
|
| 686 |
+
continue
|
| 687 |
+
|
| 688 |
+
output_tokens.append(char)
|
| 689 |
+
|
| 690 |
+
return output_tokens
|
| 691 |
+
|
| 692 |
+
|
| 693 |
+
# Copied from transformers.models.bert.tokenization_bert.BasicTokenizer
|
| 694 |
+
class BasicTokenizer:
|
| 695 |
+
"""
|
| 696 |
+
Constructs a BasicTokenizer that will run basic tokenization (punctuation splitting, lower casing, etc.).
|
| 697 |
+
|
| 698 |
+
Args:
|
| 699 |
+
do_lower_case (`bool`, *optional*, defaults to `True`):
|
| 700 |
+
Whether or not to lowercase the input when tokenizing.
|
| 701 |
+
never_split (`Iterable`, *optional*):
|
| 702 |
+
Collection of tokens which will never be split during tokenization. Only has an effect when
|
| 703 |
+
`do_basic_tokenize=True`
|
| 704 |
+
tokenize_chinese_chars (`bool`, *optional*, defaults to `True`):
|
| 705 |
+
Whether or not to tokenize Chinese characters.
|
| 706 |
+
|
| 707 |
+
This should likely be deactivated for Japanese (see this
|
| 708 |
+
[issue](https://github.com/huggingface/transformers/issues/328)).
|
| 709 |
+
strip_accents (`bool`, *optional*):
|
| 710 |
+
Whether or not to strip all accents. If this option is not specified, then it will be determined by the
|
| 711 |
+
value for `lowercase` (as in the original BERT).
|
| 712 |
+
do_split_on_punc (`bool`, *optional*, defaults to `True`):
|
| 713 |
+
In some instances we want to skip the basic punctuation splitting so that later tokenization can capture
|
| 714 |
+
the full context of the words, such as contractions.
|
| 715 |
+
"""
|
| 716 |
+
|
| 717 |
+
def __init__(
|
| 718 |
+
self,
|
| 719 |
+
do_lower_case=True,
|
| 720 |
+
never_split=None,
|
| 721 |
+
tokenize_chinese_chars=True,
|
| 722 |
+
strip_accents=None,
|
| 723 |
+
do_split_on_punc=True,
|
| 724 |
+
):
|
| 725 |
+
if never_split is None:
|
| 726 |
+
never_split = []
|
| 727 |
+
self.do_lower_case = do_lower_case
|
| 728 |
+
self.never_split = set(never_split)
|
| 729 |
+
self.tokenize_chinese_chars = tokenize_chinese_chars
|
| 730 |
+
self.strip_accents = strip_accents
|
| 731 |
+
self.do_split_on_punc = do_split_on_punc
|
| 732 |
+
|
| 733 |
+
def tokenize(self, text, never_split=None):
|
| 734 |
+
"""
|
| 735 |
+
Basic Tokenization of a piece of text. For sub-word tokenization, see WordPieceTokenizer.
|
| 736 |
+
|
| 737 |
+
Args:
|
| 738 |
+
never_split (`List[str]`, *optional*)
|
| 739 |
+
Kept for backward compatibility purposes. Now implemented directly at the base class level (see
|
| 740 |
+
[`PreTrainedTokenizer.tokenize`]) List of token not to split.
|
| 741 |
+
"""
|
| 742 |
+
# union() returns a new set by concatenating the two sets.
|
| 743 |
+
never_split = self.never_split.union(set(never_split)) if never_split else self.never_split
|
| 744 |
+
text = self._clean_text(text)
|
| 745 |
+
|
| 746 |
+
# This was added on November 1st, 2018 for the multilingual and Chinese
|
| 747 |
+
# models. This is also applied to the English models now, but it doesn't
|
| 748 |
+
# matter since the English models were not trained on any Chinese data
|
| 749 |
+
# and generally don't have any Chinese data in them (there are Chinese
|
| 750 |
+
# characters in the vocabulary because Wikipedia does have some Chinese
|
| 751 |
+
# words in the English Wikipedia.).
|
| 752 |
+
if self.tokenize_chinese_chars:
|
| 753 |
+
text = self._tokenize_chinese_chars(text)
|
| 754 |
+
# prevents treating the same character with different unicode codepoints as different characters
|
| 755 |
+
unicode_normalized_text = unicodedata.normalize("NFC", text)
|
| 756 |
+
orig_tokens = whitespace_tokenize(unicode_normalized_text)
|
| 757 |
+
split_tokens = []
|
| 758 |
+
for token in orig_tokens:
|
| 759 |
+
if token not in never_split:
|
| 760 |
+
if self.do_lower_case:
|
| 761 |
+
token = token.lower()
|
| 762 |
+
if self.strip_accents is not False:
|
| 763 |
+
token = self._run_strip_accents(token)
|
| 764 |
+
elif self.strip_accents:
|
| 765 |
+
token = self._run_strip_accents(token)
|
| 766 |
+
split_tokens.extend(self._run_split_on_punc(token, never_split))
|
| 767 |
+
|
| 768 |
+
output_tokens = whitespace_tokenize(" ".join(split_tokens))
|
| 769 |
+
return output_tokens
|
| 770 |
+
|
| 771 |
+
def _run_strip_accents(self, text):
|
| 772 |
+
"""Strips accents from a piece of text."""
|
| 773 |
+
text = unicodedata.normalize("NFD", text)
|
| 774 |
+
output = []
|
| 775 |
+
for char in text:
|
| 776 |
+
cat = unicodedata.category(char)
|
| 777 |
+
if cat == "Mn":
|
| 778 |
+
continue
|
| 779 |
+
output.append(char)
|
| 780 |
+
return "".join(output)
|
| 781 |
+
|
| 782 |
+
def _run_split_on_punc(self, text, never_split=None):
|
| 783 |
+
"""Splits punctuation on a piece of text."""
|
| 784 |
+
if not self.do_split_on_punc or (never_split is not None and text in never_split):
|
| 785 |
+
return [text]
|
| 786 |
+
chars = list(text)
|
| 787 |
+
i = 0
|
| 788 |
+
start_new_word = True
|
| 789 |
+
output = []
|
| 790 |
+
while i < len(chars):
|
| 791 |
+
char = chars[i]
|
| 792 |
+
if _is_punctuation(char):
|
| 793 |
+
output.append([char])
|
| 794 |
+
start_new_word = True
|
| 795 |
+
else:
|
| 796 |
+
if start_new_word:
|
| 797 |
+
output.append([])
|
| 798 |
+
start_new_word = False
|
| 799 |
+
output[-1].append(char)
|
| 800 |
+
i += 1
|
| 801 |
+
|
| 802 |
+
return ["".join(x) for x in output]
|
| 803 |
+
|
| 804 |
+
def _tokenize_chinese_chars(self, text):
|
| 805 |
+
"""Adds whitespace around any CJK character."""
|
| 806 |
+
output = []
|
| 807 |
+
for char in text:
|
| 808 |
+
cp = ord(char)
|
| 809 |
+
if self._is_chinese_char(cp):
|
| 810 |
+
output.append(" ")
|
| 811 |
+
output.append(char)
|
| 812 |
+
output.append(" ")
|
| 813 |
+
else:
|
| 814 |
+
output.append(char)
|
| 815 |
+
return "".join(output)
|
| 816 |
+
|
| 817 |
+
def _is_chinese_char(self, cp):
|
| 818 |
+
"""Checks whether CP is the codepoint of a CJK character."""
|
| 819 |
+
# This defines a "chinese character" as anything in the CJK Unicode block:
|
| 820 |
+
# https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block)
|
| 821 |
+
#
|
| 822 |
+
# Note that the CJK Unicode block is NOT all Japanese and Korean characters,
|
| 823 |
+
# despite its name. The modern Korean Hangul alphabet is a different block,
|
| 824 |
+
# as is Japanese Hiragana and Katakana. Those alphabets are used to write
|
| 825 |
+
# space-separated words, so they are not treated specially and handled
|
| 826 |
+
# like the all of the other languages.
|
| 827 |
+
if (
|
| 828 |
+
(cp >= 0x4E00 and cp <= 0x9FFF)
|
| 829 |
+
or (cp >= 0x3400 and cp <= 0x4DBF) #
|
| 830 |
+
or (cp >= 0x20000 and cp <= 0x2A6DF) #
|
| 831 |
+
or (cp >= 0x2A700 and cp <= 0x2B73F) #
|
| 832 |
+
or (cp >= 0x2B740 and cp <= 0x2B81F) #
|
| 833 |
+
or (cp >= 0x2B820 and cp <= 0x2CEAF) #
|
| 834 |
+
or (cp >= 0xF900 and cp <= 0xFAFF)
|
| 835 |
+
or (cp >= 0x2F800 and cp <= 0x2FA1F) #
|
| 836 |
+
): #
|
| 837 |
+
return True
|
| 838 |
+
|
| 839 |
+
return False
|
| 840 |
+
|
| 841 |
+
def _clean_text(self, text):
|
| 842 |
+
"""Performs invalid character removal and whitespace cleanup on text."""
|
| 843 |
+
output = []
|
| 844 |
+
for char in text:
|
| 845 |
+
cp = ord(char)
|
| 846 |
+
if cp == 0 or cp == 0xFFFD or _is_control(char):
|
| 847 |
+
continue
|
| 848 |
+
if _is_whitespace(char):
|
| 849 |
+
output.append(" ")
|
| 850 |
+
else:
|
| 851 |
+
output.append(char)
|
| 852 |
+
return "".join(output)
|
| 853 |
+
|
| 854 |
+
|
| 855 |
+
# Copied from transformers.models.bert.tokenization_bert.WordpieceTokenizer
|
| 856 |
+
class WordpieceTokenizer:
|
| 857 |
+
"""Runs WordPiece tokenization."""
|
| 858 |
+
|
| 859 |
+
def __init__(self, vocab, unk_token, max_input_chars_per_word=100):
|
| 860 |
+
self.vocab = vocab
|
| 861 |
+
self.unk_token = unk_token
|
| 862 |
+
self.max_input_chars_per_word = max_input_chars_per_word
|
| 863 |
+
|
| 864 |
+
def tokenize(self, text):
|
| 865 |
+
"""
|
| 866 |
+
Tokenizes a piece of text into its word pieces. This uses a greedy longest-match-first algorithm to perform
|
| 867 |
+
tokenization using the given vocabulary.
|
| 868 |
+
|
| 869 |
+
For example, `input = "unaffable"` wil return as output `["un", "##aff", "##able"]`.
|
| 870 |
+
|
| 871 |
+
Args:
|
| 872 |
+
text: A single token or whitespace separated tokens. This should have
|
| 873 |
+
already been passed through *BasicTokenizer*.
|
| 874 |
+
|
| 875 |
+
Returns:
|
| 876 |
+
A list of wordpiece tokens.
|
| 877 |
+
"""
|
| 878 |
+
|
| 879 |
+
output_tokens = []
|
| 880 |
+
for token in whitespace_tokenize(text):
|
| 881 |
+
chars = list(token)
|
| 882 |
+
if len(chars) > self.max_input_chars_per_word:
|
| 883 |
+
output_tokens.append(self.unk_token)
|
| 884 |
+
continue
|
| 885 |
+
|
| 886 |
+
is_bad = False
|
| 887 |
+
start = 0
|
| 888 |
+
sub_tokens = []
|
| 889 |
+
while start < len(chars):
|
| 890 |
+
end = len(chars)
|
| 891 |
+
cur_substr = None
|
| 892 |
+
while start < end:
|
| 893 |
+
substr = "".join(chars[start:end])
|
| 894 |
+
if start > 0:
|
| 895 |
+
substr = "##" + substr
|
| 896 |
+
if substr in self.vocab:
|
| 897 |
+
cur_substr = substr
|
| 898 |
+
break
|
| 899 |
+
end -= 1
|
| 900 |
+
if cur_substr is None:
|
| 901 |
+
is_bad = True
|
| 902 |
+
break
|
| 903 |
+
sub_tokens.append(cur_substr)
|
| 904 |
+
start = end
|
| 905 |
+
|
| 906 |
+
if is_bad:
|
| 907 |
+
output_tokens.append(self.unk_token)
|
| 908 |
+
else:
|
| 909 |
+
output_tokens.extend(sub_tokens)
|
| 910 |
+
return output_tokens
|
| 911 |
+
|
| 912 |
+
|
| 913 |
+
class SentencepieceTokenizer:
|
| 914 |
+
"""
|
| 915 |
+
Runs sentencepiece tokenization. Based on transformers.models.albert.tokenization_albert.AlbertTokenizer.
|
| 916 |
+
"""
|
| 917 |
+
|
| 918 |
+
def __init__(
|
| 919 |
+
self,
|
| 920 |
+
vocab,
|
| 921 |
+
unk_token,
|
| 922 |
+
do_lower_case=False,
|
| 923 |
+
remove_space=True,
|
| 924 |
+
keep_accents=True,
|
| 925 |
+
sp_model_kwargs: Optional[Dict[str, Any]] = None,
|
| 926 |
+
):
|
| 927 |
+
self.vocab = vocab
|
| 928 |
+
self.unk_token = unk_token
|
| 929 |
+
self.do_lower_case = do_lower_case
|
| 930 |
+
self.remove_space = remove_space
|
| 931 |
+
self.keep_accents = keep_accents
|
| 932 |
+
|
| 933 |
+
self.sp_model_kwargs = {} if sp_model_kwargs is None else sp_model_kwargs
|
| 934 |
+
self.sp_model = spm.SentencePieceProcessor(**self.sp_model_kwargs)
|
| 935 |
+
self.sp_model.Load(self.vocab)
|
| 936 |
+
|
| 937 |
+
def preprocess_text(self, inputs):
|
| 938 |
+
if self.remove_space:
|
| 939 |
+
outputs = " ".join(inputs.strip().split())
|
| 940 |
+
else:
|
| 941 |
+
outputs = inputs
|
| 942 |
+
outputs = outputs.replace("``", '"').replace("''", '"')
|
| 943 |
+
|
| 944 |
+
if not self.keep_accents:
|
| 945 |
+
outputs = unicodedata.normalize("NFKD", outputs)
|
| 946 |
+
outputs = "".join([c for c in outputs if not unicodedata.combining(c)])
|
| 947 |
+
if self.do_lower_case:
|
| 948 |
+
outputs = outputs.lower()
|
| 949 |
+
|
| 950 |
+
return outputs
|
| 951 |
+
|
| 952 |
+
def tokenize(self, text):
|
| 953 |
+
"""
|
| 954 |
+
Tokenizes text by sentencepiece. Based on [SentencePiece](https://github.com/google/sentencepiece).
|
| 955 |
+
Tokenization needs the given vocabulary.
|
| 956 |
+
|
| 957 |
+
Args:
|
| 958 |
+
text: A string needs to be tokenized.
|
| 959 |
+
|
| 960 |
+
Returns:
|
| 961 |
+
A list of sentencepiece tokens.
|
| 962 |
+
"""
|
| 963 |
+
text = self.preprocess_text(text)
|
| 964 |
+
pieces = self.sp_model.encode(text, out_type=str)
|
| 965 |
+
new_pieces = []
|
| 966 |
+
for piece in pieces:
|
| 967 |
+
if len(piece) > 1 and piece[-1] == str(",") and piece[-2].isdigit():
|
| 968 |
+
cur_pieces = self.sp_model.EncodeAsPieces(piece[:-1].replace(SPIECE_UNDERLINE, ""))
|
| 969 |
+
if piece[0] != SPIECE_UNDERLINE and cur_pieces[0][0] == SPIECE_UNDERLINE:
|
| 970 |
+
if len(cur_pieces[0]) == 1:
|
| 971 |
+
cur_pieces = cur_pieces[1:]
|
| 972 |
+
else:
|
| 973 |
+
cur_pieces[0] = cur_pieces[0][1:]
|
| 974 |
+
cur_pieces.append(piece[-1])
|
| 975 |
+
new_pieces.extend(cur_pieces)
|
| 976 |
+
else:
|
| 977 |
+
new_pieces.append(piece)
|
| 978 |
+
|
| 979 |
+
return new_pieces
|
| 980 |
+
|
| 981 |
+
|
| 982 |
+
__all__ = ["BertJapaneseTokenizer", "CharacterTokenizer", "MecabTokenizer"]
|
lib/python3.12/site-packages/transformers/models/bigbird_pegasus/__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_bigbird_pegasus import *
|
| 22 |
+
from .modeling_bigbird_pegasus 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__)
|
lib/python3.12/site-packages/transformers/models/bigbird_pegasus/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (694 Bytes). View file
|
|
|
lib/python3.12/site-packages/transformers/models/bigbird_pegasus/__pycache__/configuration_bigbird_pegasus.cpython-312.pyc
ADDED
|
Binary file (17 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/bigbird_pegasus/configuration_bigbird_pegasus.py
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright Google Research and The HuggingFace Inc. team. All rights reserved.
|
| 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 |
+
"""BigBirdPegasus model configuration"""
|
| 16 |
+
|
| 17 |
+
from collections import OrderedDict
|
| 18 |
+
from typing import Any, Mapping, Optional
|
| 19 |
+
|
| 20 |
+
from ... import PreTrainedTokenizer
|
| 21 |
+
from ...configuration_utils import PretrainedConfig
|
| 22 |
+
from ...onnx import OnnxConfig, OnnxConfigWithPast, OnnxSeq2SeqConfigWithPast
|
| 23 |
+
from ...onnx.utils import compute_effective_axis_dimension
|
| 24 |
+
from ...utils import TensorType, is_torch_available, logging
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
logger = logging.get_logger(__name__)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class BigBirdPegasusConfig(PretrainedConfig):
|
| 31 |
+
r"""
|
| 32 |
+
This is the configuration class to store the configuration of a [`BigBirdPegasusModel`]. It is used to instantiate
|
| 33 |
+
an BigBirdPegasus model according to the specified arguments, defining the model architecture. Instantiating a
|
| 34 |
+
configuration with the defaults will yield a similar configuration to that of the BigBirdPegasus
|
| 35 |
+
[google/bigbird-pegasus-large-arxiv](https://huggingface.co/google/bigbird-pegasus-large-arxiv) architecture.
|
| 36 |
+
|
| 37 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 38 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
Args:
|
| 42 |
+
vocab_size (`int`, *optional*, defaults to 96103):
|
| 43 |
+
Vocabulary size of the BigBirdPegasus model. Defines the number of different tokens that can be represented
|
| 44 |
+
by the `inputs_ids` passed when calling [`BigBirdPegasusModel`].
|
| 45 |
+
d_model (`int`, *optional*, defaults to 1024):
|
| 46 |
+
Dimension of the layers and the pooler layer.
|
| 47 |
+
encoder_layers (`int`, *optional*, defaults to 16):
|
| 48 |
+
Number of encoder layers.
|
| 49 |
+
decoder_layers (`int`, *optional*, defaults to 16):
|
| 50 |
+
Number of decoder layers.
|
| 51 |
+
encoder_attention_heads (`int`, *optional*, defaults to 16):
|
| 52 |
+
Number of attention heads for each attention layer in the Transformer encoder.
|
| 53 |
+
decoder_attention_heads (`int`, *optional*, defaults to 16):
|
| 54 |
+
Number of attention heads for each attention layer in the Transformer decoder.
|
| 55 |
+
decoder_ffn_dim (`int`, *optional*, defaults to 4096):
|
| 56 |
+
Dimension of the "intermediate" (often named feed-forward) layer in decoder.
|
| 57 |
+
encoder_ffn_dim (`int`, *optional*, defaults to 4096):
|
| 58 |
+
Dimension of the "intermediate" (often named feed-forward) layer in decoder.
|
| 59 |
+
activation_function (`str` or `function`, *optional*, defaults to `"gelu_new"`):
|
| 60 |
+
The non-linear activation function (function or string) in the encoder and pooler. If string, `"gelu"`,
|
| 61 |
+
`"relu"`, `"silu"` and `"gelu_new"` are supported.
|
| 62 |
+
dropout (`float`, *optional*, defaults to 0.1):
|
| 63 |
+
The dropout probability for all fully connected layers in the embeddings, encoder, and pooler.
|
| 64 |
+
attention_dropout (`float`, *optional*, defaults to 0.0):
|
| 65 |
+
The dropout ratio for the attention probabilities.
|
| 66 |
+
activation_dropout (`float`, *optional*, defaults to 0.0):
|
| 67 |
+
The dropout ratio for activations inside the fully connected layer.
|
| 68 |
+
classifier_dropout (`float`, *optional*, defaults to 0.0):
|
| 69 |
+
The dropout ratio for classifier.
|
| 70 |
+
max_position_embeddings (`int`, *optional*, defaults to 4096):
|
| 71 |
+
The maximum sequence length that this model might ever be used with. Typically set this to something large
|
| 72 |
+
just in case (e.g., 1024 or 2048 or 4096).
|
| 73 |
+
init_std (`float`, *optional*, defaults to 0.02):
|
| 74 |
+
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
| 75 |
+
encoder_layerdrop (`float`, *optional*, defaults to 0.0):
|
| 76 |
+
The LayerDrop probability for the encoder. See the [LayerDrop paper](see https://arxiv.org/abs/1909.11556)
|
| 77 |
+
for more details.
|
| 78 |
+
decoder_layerdrop (`float`, *optional*, defaults to 0.0):
|
| 79 |
+
The LayerDrop probability for the decoder. See the [LayerDrop paper](see https://arxiv.org/abs/1909.11556)
|
| 80 |
+
for more details.
|
| 81 |
+
use_cache (`bool`, *optional*, defaults to `True`):
|
| 82 |
+
Whether or not the model should return the last key/values attentions (not used by all models).
|
| 83 |
+
attention_type (`str`, *optional*, defaults to `"block_sparse"`)
|
| 84 |
+
Whether to use block sparse attention (with n complexity) as introduced in paper or original attention
|
| 85 |
+
layer (with n^2 complexity) in encoder. Possible values are `"original_full"` and `"block_sparse"`.
|
| 86 |
+
use_bias (`bool`, *optional*, defaults to `False`)
|
| 87 |
+
Whether to use bias in query, key, value.
|
| 88 |
+
block_size (`int`, *optional*, defaults to 64)
|
| 89 |
+
Size of each block. Useful only when `attention_type == "block_sparse"`.
|
| 90 |
+
num_random_blocks (`int`, *optional*, defaults to 3)
|
| 91 |
+
Each query is going to attend these many number of random blocks. Useful only when `attention_type ==
|
| 92 |
+
"block_sparse"`.
|
| 93 |
+
scale_embeddings (`bool`, *optional*, defaults to `True`)
|
| 94 |
+
Whether to rescale embeddings with (hidden_size ** 0.5).
|
| 95 |
+
|
| 96 |
+
Example:
|
| 97 |
+
|
| 98 |
+
```python
|
| 99 |
+
>>> from transformers import BigBirdPegasusConfig, BigBirdPegasusModel
|
| 100 |
+
|
| 101 |
+
>>> # Initializing a BigBirdPegasus bigbird-pegasus-base style configuration
|
| 102 |
+
>>> configuration = BigBirdPegasusConfig()
|
| 103 |
+
|
| 104 |
+
>>> # Initializing a model (with random weights) from the bigbird-pegasus-base style configuration
|
| 105 |
+
>>> model = BigBirdPegasusModel(configuration)
|
| 106 |
+
|
| 107 |
+
>>> # Accessing the model configuration
|
| 108 |
+
>>> configuration = model.config
|
| 109 |
+
```"""
|
| 110 |
+
|
| 111 |
+
model_type = "bigbird_pegasus"
|
| 112 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 113 |
+
attribute_map = {
|
| 114 |
+
"num_attention_heads": "encoder_attention_heads",
|
| 115 |
+
"hidden_size": "d_model",
|
| 116 |
+
"attention_probs_dropout_prob": "attention_dropout",
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
def __init__(
|
| 120 |
+
self,
|
| 121 |
+
vocab_size=96103,
|
| 122 |
+
max_position_embeddings=4096,
|
| 123 |
+
encoder_layers=16,
|
| 124 |
+
encoder_ffn_dim=4096,
|
| 125 |
+
encoder_attention_heads=16,
|
| 126 |
+
decoder_layers=16,
|
| 127 |
+
decoder_ffn_dim=4096,
|
| 128 |
+
decoder_attention_heads=16,
|
| 129 |
+
encoder_layerdrop=0.0,
|
| 130 |
+
decoder_layerdrop=0.0,
|
| 131 |
+
use_cache=True,
|
| 132 |
+
is_encoder_decoder=True,
|
| 133 |
+
activation_function="gelu_new",
|
| 134 |
+
d_model=1024,
|
| 135 |
+
dropout=0.1,
|
| 136 |
+
attention_dropout=0.0,
|
| 137 |
+
activation_dropout=0.0,
|
| 138 |
+
init_std=0.02,
|
| 139 |
+
decoder_start_token_id=2,
|
| 140 |
+
classifier_dropout=0.0,
|
| 141 |
+
scale_embedding=True,
|
| 142 |
+
pad_token_id=0,
|
| 143 |
+
bos_token_id=2,
|
| 144 |
+
eos_token_id=1,
|
| 145 |
+
attention_type="block_sparse", # only for encoder
|
| 146 |
+
block_size=64,
|
| 147 |
+
num_random_blocks=3,
|
| 148 |
+
use_bias=False,
|
| 149 |
+
**kwargs,
|
| 150 |
+
):
|
| 151 |
+
self.vocab_size = vocab_size
|
| 152 |
+
self.max_position_embeddings = max_position_embeddings
|
| 153 |
+
self.d_model = d_model
|
| 154 |
+
self.encoder_ffn_dim = encoder_ffn_dim
|
| 155 |
+
self.encoder_layers = encoder_layers
|
| 156 |
+
self.encoder_attention_heads = encoder_attention_heads
|
| 157 |
+
self.decoder_ffn_dim = decoder_ffn_dim
|
| 158 |
+
self.decoder_layers = decoder_layers
|
| 159 |
+
self.decoder_attention_heads = decoder_attention_heads
|
| 160 |
+
self.dropout = dropout
|
| 161 |
+
self.attention_dropout = attention_dropout
|
| 162 |
+
self.activation_dropout = activation_dropout
|
| 163 |
+
self.activation_function = activation_function
|
| 164 |
+
self.init_std = init_std
|
| 165 |
+
self.encoder_layerdrop = encoder_layerdrop
|
| 166 |
+
self.decoder_layerdrop = decoder_layerdrop
|
| 167 |
+
self.classifier_dropout = classifier_dropout
|
| 168 |
+
self.use_cache = use_cache
|
| 169 |
+
self.num_hidden_layers = encoder_layers
|
| 170 |
+
self.scale_embedding = scale_embedding # scale factor will be sqrt(d_model) if True
|
| 171 |
+
|
| 172 |
+
# extra config
|
| 173 |
+
self.attention_type = attention_type
|
| 174 |
+
self.block_size = block_size
|
| 175 |
+
self.num_random_blocks = num_random_blocks
|
| 176 |
+
self.use_bias = use_bias
|
| 177 |
+
|
| 178 |
+
super().__init__(
|
| 179 |
+
pad_token_id=pad_token_id,
|
| 180 |
+
bos_token_id=bos_token_id,
|
| 181 |
+
eos_token_id=eos_token_id,
|
| 182 |
+
is_encoder_decoder=is_encoder_decoder,
|
| 183 |
+
decoder_start_token_id=decoder_start_token_id,
|
| 184 |
+
**kwargs,
|
| 185 |
+
)
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
# Copied from transformers.models.bart.configuration_bart.BartOnnxConfig
|
| 189 |
+
class BigBirdPegasusOnnxConfig(OnnxSeq2SeqConfigWithPast):
|
| 190 |
+
@property
|
| 191 |
+
def inputs(self) -> Mapping[str, Mapping[int, str]]:
|
| 192 |
+
if self.task in ["default", "seq2seq-lm"]:
|
| 193 |
+
common_inputs = OrderedDict(
|
| 194 |
+
[
|
| 195 |
+
("input_ids", {0: "batch", 1: "encoder_sequence"}),
|
| 196 |
+
("attention_mask", {0: "batch", 1: "encoder_sequence"}),
|
| 197 |
+
]
|
| 198 |
+
)
|
| 199 |
+
|
| 200 |
+
if self.use_past:
|
| 201 |
+
common_inputs["decoder_input_ids"] = {0: "batch"}
|
| 202 |
+
common_inputs["decoder_attention_mask"] = {0: "batch", 1: "past_decoder_sequence + sequence"}
|
| 203 |
+
else:
|
| 204 |
+
common_inputs["decoder_input_ids"] = {0: "batch", 1: "decoder_sequence"}
|
| 205 |
+
common_inputs["decoder_attention_mask"] = {0: "batch", 1: "decoder_sequence"}
|
| 206 |
+
|
| 207 |
+
if self.use_past:
|
| 208 |
+
self.fill_with_past_key_values_(common_inputs, direction="inputs")
|
| 209 |
+
elif self.task == "causal-lm":
|
| 210 |
+
# TODO: figure this case out.
|
| 211 |
+
common_inputs = OrderedDict(
|
| 212 |
+
[
|
| 213 |
+
("input_ids", {0: "batch", 1: "encoder_sequence"}),
|
| 214 |
+
("attention_mask", {0: "batch", 1: "encoder_sequence"}),
|
| 215 |
+
]
|
| 216 |
+
)
|
| 217 |
+
if self.use_past:
|
| 218 |
+
num_encoder_layers, _ = self.num_layers
|
| 219 |
+
for i in range(num_encoder_layers):
|
| 220 |
+
common_inputs[f"past_key_values.{i}.key"] = {0: "batch", 2: "past_sequence + sequence"}
|
| 221 |
+
common_inputs[f"past_key_values.{i}.value"] = {0: "batch", 2: "past_sequence + sequence"}
|
| 222 |
+
else:
|
| 223 |
+
common_inputs = OrderedDict(
|
| 224 |
+
[
|
| 225 |
+
("input_ids", {0: "batch", 1: "encoder_sequence"}),
|
| 226 |
+
("attention_mask", {0: "batch", 1: "encoder_sequence"}),
|
| 227 |
+
("decoder_input_ids", {0: "batch", 1: "decoder_sequence"}),
|
| 228 |
+
("decoder_attention_mask", {0: "batch", 1: "decoder_sequence"}),
|
| 229 |
+
]
|
| 230 |
+
)
|
| 231 |
+
|
| 232 |
+
return common_inputs
|
| 233 |
+
|
| 234 |
+
@property
|
| 235 |
+
def outputs(self) -> Mapping[str, Mapping[int, str]]:
|
| 236 |
+
if self.task in ["default", "seq2seq-lm"]:
|
| 237 |
+
common_outputs = super().outputs
|
| 238 |
+
else:
|
| 239 |
+
common_outputs = super(OnnxConfigWithPast, self).outputs
|
| 240 |
+
if self.use_past:
|
| 241 |
+
num_encoder_layers, _ = self.num_layers
|
| 242 |
+
for i in range(num_encoder_layers):
|
| 243 |
+
common_outputs[f"present.{i}.key"] = {0: "batch", 2: "past_sequence + sequence"}
|
| 244 |
+
common_outputs[f"present.{i}.value"] = {0: "batch", 2: "past_sequence + sequence"}
|
| 245 |
+
return common_outputs
|
| 246 |
+
|
| 247 |
+
def _generate_dummy_inputs_for_default_and_seq2seq_lm(
|
| 248 |
+
self,
|
| 249 |
+
tokenizer: PreTrainedTokenizer,
|
| 250 |
+
batch_size: int = -1,
|
| 251 |
+
seq_length: int = -1,
|
| 252 |
+
is_pair: bool = False,
|
| 253 |
+
framework: Optional[TensorType] = None,
|
| 254 |
+
) -> Mapping[str, Any]:
|
| 255 |
+
encoder_inputs = self._generate_dummy_inputs_for_sequence_classification_and_question_answering(
|
| 256 |
+
tokenizer, batch_size, seq_length, is_pair, framework
|
| 257 |
+
)
|
| 258 |
+
|
| 259 |
+
# Generate decoder inputs
|
| 260 |
+
decoder_seq_length = seq_length if not self.use_past else 1
|
| 261 |
+
decoder_inputs = self._generate_dummy_inputs_for_sequence_classification_and_question_answering(
|
| 262 |
+
tokenizer, batch_size, decoder_seq_length, is_pair, framework
|
| 263 |
+
)
|
| 264 |
+
decoder_inputs = {f"decoder_{name}": tensor for name, tensor in decoder_inputs.items()}
|
| 265 |
+
common_inputs = dict(**encoder_inputs, **decoder_inputs)
|
| 266 |
+
|
| 267 |
+
if self.use_past:
|
| 268 |
+
if not is_torch_available():
|
| 269 |
+
raise ValueError("Cannot generate dummy past_keys inputs without PyTorch installed.")
|
| 270 |
+
else:
|
| 271 |
+
import torch
|
| 272 |
+
batch, encoder_seq_length = common_inputs["input_ids"].shape
|
| 273 |
+
decoder_seq_length = common_inputs["decoder_input_ids"].shape[1]
|
| 274 |
+
num_encoder_attention_heads, num_decoder_attention_heads = self.num_attention_heads
|
| 275 |
+
encoder_shape = (
|
| 276 |
+
batch,
|
| 277 |
+
num_encoder_attention_heads,
|
| 278 |
+
encoder_seq_length,
|
| 279 |
+
self._config.hidden_size // num_encoder_attention_heads,
|
| 280 |
+
)
|
| 281 |
+
decoder_past_length = decoder_seq_length + 3
|
| 282 |
+
decoder_shape = (
|
| 283 |
+
batch,
|
| 284 |
+
num_decoder_attention_heads,
|
| 285 |
+
decoder_past_length,
|
| 286 |
+
self._config.hidden_size // num_decoder_attention_heads,
|
| 287 |
+
)
|
| 288 |
+
|
| 289 |
+
common_inputs["decoder_attention_mask"] = torch.cat(
|
| 290 |
+
[common_inputs["decoder_attention_mask"], torch.ones(batch, decoder_past_length)], dim=1
|
| 291 |
+
)
|
| 292 |
+
|
| 293 |
+
common_inputs["past_key_values"] = []
|
| 294 |
+
# If the number of encoder and decoder layers are present in the model configuration, both are considered
|
| 295 |
+
num_encoder_layers, num_decoder_layers = self.num_layers
|
| 296 |
+
min_num_layers = min(num_encoder_layers, num_decoder_layers)
|
| 297 |
+
max_num_layers = max(num_encoder_layers, num_decoder_layers) - min_num_layers
|
| 298 |
+
remaining_side_name = "encoder" if num_encoder_layers > num_decoder_layers else "decoder"
|
| 299 |
+
|
| 300 |
+
for _ in range(min_num_layers):
|
| 301 |
+
common_inputs["past_key_values"].append(
|
| 302 |
+
(
|
| 303 |
+
torch.zeros(decoder_shape),
|
| 304 |
+
torch.zeros(decoder_shape),
|
| 305 |
+
torch.zeros(encoder_shape),
|
| 306 |
+
torch.zeros(encoder_shape),
|
| 307 |
+
)
|
| 308 |
+
)
|
| 309 |
+
# TODO: test this.
|
| 310 |
+
shape = encoder_shape if remaining_side_name == "encoder" else decoder_shape
|
| 311 |
+
for _ in range(min_num_layers, max_num_layers):
|
| 312 |
+
common_inputs["past_key_values"].append((torch.zeros(shape), torch.zeros(shape)))
|
| 313 |
+
return common_inputs
|
| 314 |
+
|
| 315 |
+
def _generate_dummy_inputs_for_causal_lm(
|
| 316 |
+
self,
|
| 317 |
+
tokenizer: PreTrainedTokenizer,
|
| 318 |
+
batch_size: int = -1,
|
| 319 |
+
seq_length: int = -1,
|
| 320 |
+
is_pair: bool = False,
|
| 321 |
+
framework: Optional[TensorType] = None,
|
| 322 |
+
) -> Mapping[str, Any]:
|
| 323 |
+
common_inputs = self._generate_dummy_inputs_for_sequence_classification_and_question_answering(
|
| 324 |
+
tokenizer, batch_size, seq_length, is_pair, framework
|
| 325 |
+
)
|
| 326 |
+
|
| 327 |
+
if self.use_past:
|
| 328 |
+
if not is_torch_available():
|
| 329 |
+
raise ValueError("Cannot generate dummy past_keys inputs without PyTorch installed.")
|
| 330 |
+
else:
|
| 331 |
+
import torch
|
| 332 |
+
batch, seqlen = common_inputs["input_ids"].shape
|
| 333 |
+
# Not using the same length for past_key_values
|
| 334 |
+
past_key_values_length = seqlen + 2
|
| 335 |
+
num_encoder_layers, _ = self.num_layers
|
| 336 |
+
num_encoder_attention_heads, _ = self.num_attention_heads
|
| 337 |
+
past_shape = (
|
| 338 |
+
batch,
|
| 339 |
+
num_encoder_attention_heads,
|
| 340 |
+
past_key_values_length,
|
| 341 |
+
self._config.hidden_size // num_encoder_attention_heads,
|
| 342 |
+
)
|
| 343 |
+
|
| 344 |
+
mask_dtype = common_inputs["attention_mask"].dtype
|
| 345 |
+
common_inputs["attention_mask"] = torch.cat(
|
| 346 |
+
[common_inputs["attention_mask"], torch.ones(batch, past_key_values_length, dtype=mask_dtype)], dim=1
|
| 347 |
+
)
|
| 348 |
+
common_inputs["past_key_values"] = [
|
| 349 |
+
(torch.zeros(past_shape), torch.zeros(past_shape)) for _ in range(num_encoder_layers)
|
| 350 |
+
]
|
| 351 |
+
return common_inputs
|
| 352 |
+
|
| 353 |
+
def _generate_dummy_inputs_for_sequence_classification_and_question_answering(
|
| 354 |
+
self,
|
| 355 |
+
tokenizer: PreTrainedTokenizer,
|
| 356 |
+
batch_size: int = -1,
|
| 357 |
+
seq_length: int = -1,
|
| 358 |
+
is_pair: bool = False,
|
| 359 |
+
framework: Optional[TensorType] = None,
|
| 360 |
+
) -> Mapping[str, Any]:
|
| 361 |
+
# Copied from OnnxConfig.generate_dummy_inputs
|
| 362 |
+
# Did not use super(OnnxConfigWithPast, self).generate_dummy_inputs for code clarity.
|
| 363 |
+
# If dynamic axis (-1) we forward with a fixed dimension of 2 samples to avoid optimizations made by ONNX
|
| 364 |
+
batch_size = compute_effective_axis_dimension(
|
| 365 |
+
batch_size, fixed_dimension=OnnxConfig.default_fixed_batch, num_token_to_add=0
|
| 366 |
+
)
|
| 367 |
+
|
| 368 |
+
# If dynamic axis (-1) we forward with a fixed dimension of 8 tokens to avoid optimizations made by ONNX
|
| 369 |
+
token_to_add = tokenizer.num_special_tokens_to_add(is_pair)
|
| 370 |
+
seq_length = compute_effective_axis_dimension(
|
| 371 |
+
seq_length, fixed_dimension=OnnxConfig.default_fixed_sequence, num_token_to_add=token_to_add
|
| 372 |
+
)
|
| 373 |
+
|
| 374 |
+
# Generate dummy inputs according to compute batch and sequence
|
| 375 |
+
dummy_input = [" ".join([tokenizer.unk_token]) * seq_length] * batch_size
|
| 376 |
+
common_inputs = dict(tokenizer(dummy_input, return_tensors=framework))
|
| 377 |
+
return common_inputs
|
| 378 |
+
|
| 379 |
+
def generate_dummy_inputs(
|
| 380 |
+
self,
|
| 381 |
+
tokenizer: PreTrainedTokenizer,
|
| 382 |
+
batch_size: int = -1,
|
| 383 |
+
seq_length: int = -1,
|
| 384 |
+
is_pair: bool = False,
|
| 385 |
+
framework: Optional[TensorType] = None,
|
| 386 |
+
) -> Mapping[str, Any]:
|
| 387 |
+
if self.task in ["default", "seq2seq-lm"]:
|
| 388 |
+
common_inputs = self._generate_dummy_inputs_for_default_and_seq2seq_lm(
|
| 389 |
+
tokenizer, batch_size=batch_size, seq_length=seq_length, is_pair=is_pair, framework=framework
|
| 390 |
+
)
|
| 391 |
+
|
| 392 |
+
elif self.task == "causal-lm":
|
| 393 |
+
common_inputs = self._generate_dummy_inputs_for_causal_lm(
|
| 394 |
+
tokenizer, batch_size=batch_size, seq_length=seq_length, is_pair=is_pair, framework=framework
|
| 395 |
+
)
|
| 396 |
+
else:
|
| 397 |
+
common_inputs = self._generate_dummy_inputs_for_sequence_classification_and_question_answering(
|
| 398 |
+
tokenizer, batch_size=batch_size, seq_length=seq_length, is_pair=is_pair, framework=framework
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
return common_inputs
|
| 402 |
+
|
| 403 |
+
def _flatten_past_key_values_(self, flattened_output, name, idx, t):
|
| 404 |
+
if self.task in ["default", "seq2seq-lm"]:
|
| 405 |
+
flattened_output = super()._flatten_past_key_values_(flattened_output, name, idx, t)
|
| 406 |
+
else:
|
| 407 |
+
flattened_output = super(OnnxSeq2SeqConfigWithPast, self)._flatten_past_key_values_(
|
| 408 |
+
flattened_output, name, idx, t
|
| 409 |
+
)
|
| 410 |
+
|
| 411 |
+
|
| 412 |
+
__all__ = ["BigBirdPegasusConfig", "BigBirdPegasusOnnxConfig"]
|
lib/python3.12/site-packages/transformers/models/bigbird_pegasus/modeling_bigbird_pegasus.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
lib/python3.12/site-packages/transformers/models/bros/__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_bros import *
|
| 22 |
+
from .modeling_bros import *
|
| 23 |
+
from .processing_bros 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__)
|
lib/python3.12/site-packages/transformers/models/bros/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (691 Bytes). View file
|
|
|
lib/python3.12/site-packages/transformers/models/bros/__pycache__/configuration_bros.cpython-312.pyc
ADDED
|
Binary file (5.85 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/bros/__pycache__/modeling_bros.cpython-312.pyc
ADDED
|
Binary file (62.8 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/bros/__pycache__/processing_bros.cpython-312.pyc
ADDED
|
Binary file (4.33 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/bros/configuration_bros.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2023-present NAVER Corp, The Microsoft Research Asia LayoutLM Team Authors and the HuggingFace Inc. team.
|
| 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 |
+
"""Bros model configuration"""
|
| 16 |
+
|
| 17 |
+
from ...configuration_utils import PretrainedConfig
|
| 18 |
+
from ...utils import logging
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
logger = logging.get_logger(__name__)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class BrosConfig(PretrainedConfig):
|
| 25 |
+
r"""
|
| 26 |
+
This is the configuration class to store the configuration of a [`BrosModel`] or a [`TFBrosModel`]. It is used to
|
| 27 |
+
instantiate a Bros model according to the specified arguments, defining the model architecture. Instantiating a
|
| 28 |
+
configuration with the defaults will yield a similar configuration to that of the Bros
|
| 29 |
+
[jinho8345/bros-base-uncased](https://huggingface.co/jinho8345/bros-base-uncased) architecture.
|
| 30 |
+
|
| 31 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 32 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 33 |
+
|
| 34 |
+
Args:
|
| 35 |
+
vocab_size (`int`, *optional*, defaults to 30522):
|
| 36 |
+
Vocabulary size of the Bros model. Defines the number of different tokens that can be represented by the
|
| 37 |
+
`inputs_ids` passed when calling [`BrosModel`] or [`TFBrosModel`].
|
| 38 |
+
hidden_size (`int`, *optional*, defaults to 768):
|
| 39 |
+
Dimensionality of the encoder layers and the pooler layer.
|
| 40 |
+
num_hidden_layers (`int`, *optional*, defaults to 12):
|
| 41 |
+
Number of hidden layers in the Transformer encoder.
|
| 42 |
+
num_attention_heads (`int`, *optional*, defaults to 12):
|
| 43 |
+
Number of attention heads for each attention layer in the Transformer encoder.
|
| 44 |
+
intermediate_size (`int`, *optional*, defaults to 3072):
|
| 45 |
+
Dimensionality of the "intermediate" (often named feed-forward) layer in the Transformer encoder.
|
| 46 |
+
hidden_act (`str` or `Callable`, *optional*, defaults to `"gelu"`):
|
| 47 |
+
The non-linear activation function (function or string) in the encoder and pooler. If string, `"gelu"`,
|
| 48 |
+
`"relu"`, `"silu"` and `"gelu_new"` are supported.
|
| 49 |
+
hidden_dropout_prob (`float`, *optional*, defaults to 0.1):
|
| 50 |
+
The dropout probability for all fully connected layers in the embeddings, encoder, and pooler.
|
| 51 |
+
attention_probs_dropout_prob (`float`, *optional*, defaults to 0.1):
|
| 52 |
+
The dropout ratio for the attention probabilities.
|
| 53 |
+
max_position_embeddings (`int`, *optional*, defaults to 512):
|
| 54 |
+
The maximum sequence length that this model might ever be used with. Typically set this to something large
|
| 55 |
+
just in case (e.g., 512 or 1024 or 2048).
|
| 56 |
+
type_vocab_size (`int`, *optional*, defaults to 2):
|
| 57 |
+
The vocabulary size of the `token_type_ids` passed when calling [`BrosModel`] or [`TFBrosModel`].
|
| 58 |
+
initializer_range (`float`, *optional*, defaults to 0.02):
|
| 59 |
+
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
| 60 |
+
layer_norm_eps (`float`, *optional*, defaults to 1e-12):
|
| 61 |
+
The epsilon used by the layer normalization layers.
|
| 62 |
+
pad_token_id (`int`, *optional*, defaults to 0):
|
| 63 |
+
The index of the padding token in the token vocabulary.
|
| 64 |
+
dim_bbox (`int`, *optional*, defaults to 8):
|
| 65 |
+
The dimension of the bounding box coordinates. (x0, y1, x1, y0, x1, y1, x0, y1)
|
| 66 |
+
bbox_scale (`float`, *optional*, defaults to 100.0):
|
| 67 |
+
The scale factor of the bounding box coordinates.
|
| 68 |
+
n_relations (`int`, *optional*, defaults to 1):
|
| 69 |
+
The number of relations for SpadeEE(entity extraction), SpadeEL(entity linking) head.
|
| 70 |
+
classifier_dropout_prob (`float`, *optional*, defaults to 0.1):
|
| 71 |
+
The dropout ratio for the classifier head.
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
Examples:
|
| 75 |
+
|
| 76 |
+
```python
|
| 77 |
+
>>> from transformers import BrosConfig, BrosModel
|
| 78 |
+
|
| 79 |
+
>>> # Initializing a BROS jinho8345/bros-base-uncased style configuration
|
| 80 |
+
>>> configuration = BrosConfig()
|
| 81 |
+
|
| 82 |
+
>>> # Initializing a model from the jinho8345/bros-base-uncased style configuration
|
| 83 |
+
>>> model = BrosModel(configuration)
|
| 84 |
+
|
| 85 |
+
>>> # Accessing the model configuration
|
| 86 |
+
>>> configuration = model.config
|
| 87 |
+
```"""
|
| 88 |
+
|
| 89 |
+
model_type = "bros"
|
| 90 |
+
|
| 91 |
+
def __init__(
|
| 92 |
+
self,
|
| 93 |
+
vocab_size=30522,
|
| 94 |
+
hidden_size=768,
|
| 95 |
+
num_hidden_layers=12,
|
| 96 |
+
num_attention_heads=12,
|
| 97 |
+
intermediate_size=3072,
|
| 98 |
+
hidden_act="gelu",
|
| 99 |
+
hidden_dropout_prob=0.1,
|
| 100 |
+
attention_probs_dropout_prob=0.1,
|
| 101 |
+
max_position_embeddings=512,
|
| 102 |
+
type_vocab_size=2,
|
| 103 |
+
initializer_range=0.02,
|
| 104 |
+
layer_norm_eps=1e-12,
|
| 105 |
+
pad_token_id=0,
|
| 106 |
+
dim_bbox=8,
|
| 107 |
+
bbox_scale=100.0,
|
| 108 |
+
n_relations=1,
|
| 109 |
+
classifier_dropout_prob=0.1,
|
| 110 |
+
**kwargs,
|
| 111 |
+
):
|
| 112 |
+
super().__init__(
|
| 113 |
+
vocab_size=vocab_size,
|
| 114 |
+
hidden_size=hidden_size,
|
| 115 |
+
num_hidden_layers=num_hidden_layers,
|
| 116 |
+
num_attention_heads=num_attention_heads,
|
| 117 |
+
intermediate_size=intermediate_size,
|
| 118 |
+
hidden_act=hidden_act,
|
| 119 |
+
hidden_dropout_prob=hidden_dropout_prob,
|
| 120 |
+
attention_probs_dropout_prob=attention_probs_dropout_prob,
|
| 121 |
+
max_position_embeddings=max_position_embeddings,
|
| 122 |
+
type_vocab_size=type_vocab_size,
|
| 123 |
+
initializer_range=initializer_range,
|
| 124 |
+
layer_norm_eps=layer_norm_eps,
|
| 125 |
+
pad_token_id=pad_token_id,
|
| 126 |
+
**kwargs,
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
self.dim_bbox = dim_bbox
|
| 130 |
+
self.bbox_scale = bbox_scale
|
| 131 |
+
self.n_relations = n_relations
|
| 132 |
+
self.dim_bbox_sinusoid_emb_2d = self.hidden_size // 4
|
| 133 |
+
self.dim_bbox_sinusoid_emb_1d = self.dim_bbox_sinusoid_emb_2d // self.dim_bbox
|
| 134 |
+
self.dim_bbox_projection = self.hidden_size // self.num_attention_heads
|
| 135 |
+
self.classifier_dropout_prob = classifier_dropout_prob
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
__all__ = ["BrosConfig"]
|
lib/python3.12/site-packages/transformers/models/bros/modeling_bros.py
ADDED
|
@@ -0,0 +1,1323 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2023-present NAVER Corp, The Microsoft Research Asia LayoutLM Team Authors and the HuggingFace Inc. team.
|
| 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 |
+
"""PyTorch Bros model."""
|
| 16 |
+
|
| 17 |
+
import math
|
| 18 |
+
from dataclasses import dataclass
|
| 19 |
+
from typing import List, Optional, Tuple, Union
|
| 20 |
+
|
| 21 |
+
import torch
|
| 22 |
+
import torch.utils.checkpoint
|
| 23 |
+
from torch import nn
|
| 24 |
+
from torch.nn import CrossEntropyLoss
|
| 25 |
+
|
| 26 |
+
from ...activations import ACT2FN
|
| 27 |
+
from ...modeling_outputs import (
|
| 28 |
+
BaseModelOutputWithPastAndCrossAttentions,
|
| 29 |
+
BaseModelOutputWithPoolingAndCrossAttentions,
|
| 30 |
+
TokenClassifierOutput,
|
| 31 |
+
)
|
| 32 |
+
from ...modeling_utils import PreTrainedModel
|
| 33 |
+
from ...pytorch_utils import apply_chunking_to_forward, find_pruneable_heads_and_indices, prune_linear_layer
|
| 34 |
+
from ...utils import (
|
| 35 |
+
ModelOutput,
|
| 36 |
+
add_start_docstrings,
|
| 37 |
+
add_start_docstrings_to_model_forward,
|
| 38 |
+
logging,
|
| 39 |
+
replace_return_docstrings,
|
| 40 |
+
)
|
| 41 |
+
from .configuration_bros import BrosConfig
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
logger = logging.get_logger(__name__)
|
| 45 |
+
|
| 46 |
+
_CHECKPOINT_FOR_DOC = "jinho8345/bros-base-uncased"
|
| 47 |
+
_CONFIG_FOR_DOC = "BrosConfig"
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
BROS_START_DOCSTRING = r"""
|
| 51 |
+
This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass.
|
| 52 |
+
Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage
|
| 53 |
+
and behavior.
|
| 54 |
+
|
| 55 |
+
Parameters:
|
| 56 |
+
config ([`BrosConfig`]): Model configuration class with all the parameters of the model.
|
| 57 |
+
Initializing with a config file does not load the weights associated with the model, only the
|
| 58 |
+
configuration. Check out the [`~PreTrainedModel.from_pretrained`] method to load the model weights.
|
| 59 |
+
"""
|
| 60 |
+
|
| 61 |
+
BROS_INPUTS_DOCSTRING = r"""
|
| 62 |
+
Args:
|
| 63 |
+
input_ids (`torch.LongTensor` of shape `({0})`):
|
| 64 |
+
Indices of input sequence tokens in the vocabulary.
|
| 65 |
+
|
| 66 |
+
Indices can be obtained using [`BrosProcessor`]. See [`PreTrainedTokenizer.encode`] and
|
| 67 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 68 |
+
|
| 69 |
+
[What are input IDs?](../glossary#input-ids)
|
| 70 |
+
|
| 71 |
+
bbox ('torch.FloatTensor' of shape '(batch_size, num_boxes, 4)'):
|
| 72 |
+
Bounding box coordinates for each token in the input sequence. Each bounding box is a list of four values
|
| 73 |
+
(x1, y1, x2, y2), where (x1, y1) is the top left corner, and (x2, y2) is the bottom right corner of the
|
| 74 |
+
bounding box.
|
| 75 |
+
|
| 76 |
+
attention_mask (`torch.FloatTensor` of shape `({0})`, *optional*):
|
| 77 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 78 |
+
|
| 79 |
+
- 1 for tokens that are **not masked**,
|
| 80 |
+
- 0 for tokens that are **masked**.
|
| 81 |
+
|
| 82 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 83 |
+
|
| 84 |
+
bbox_first_token_mask (`torch.FloatTensor` of shape `({0})`, *optional*):
|
| 85 |
+
Mask to indicate the first token of each bounding box. Mask values selected in `[0, 1]`:
|
| 86 |
+
|
| 87 |
+
- 1 for tokens that are **not masked**,
|
| 88 |
+
- 0 for tokens that are **masked**.
|
| 89 |
+
|
| 90 |
+
token_type_ids (`torch.LongTensor` of shape `({0})`, *optional*):
|
| 91 |
+
Segment token indices to indicate first and second portions of the inputs. Indices are selected in `[0,
|
| 92 |
+
1]`:
|
| 93 |
+
|
| 94 |
+
- 0 corresponds to a *sentence A* token,
|
| 95 |
+
- 1 corresponds to a *sentence B* token.
|
| 96 |
+
|
| 97 |
+
[What are token type IDs?](../glossary#token-type-ids)
|
| 98 |
+
|
| 99 |
+
position_ids (`torch.LongTensor` of shape `({0})`, *optional*):
|
| 100 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 101 |
+
config.max_position_embeddings - 1]`.
|
| 102 |
+
|
| 103 |
+
[What are position IDs?](../glossary#position-ids)
|
| 104 |
+
|
| 105 |
+
head_mask (`torch.FloatTensor` of shape `(num_heads,)` or `(num_layers, num_heads)`, *optional*):
|
| 106 |
+
Mask to nullify selected heads of the self-attention modules. Mask values selected in `[0, 1]`:
|
| 107 |
+
|
| 108 |
+
- 1 indicates the head is **not masked**,
|
| 109 |
+
- 0 indicates the head is **masked**.
|
| 110 |
+
|
| 111 |
+
inputs_embeds (`torch.FloatTensor` of shape `({0}, hidden_size)`, *optional*):
|
| 112 |
+
Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation. This
|
| 113 |
+
is useful if you want more control over how to convert `input_ids` indices into associated vectors than the
|
| 114 |
+
model's internal embedding lookup matrix.
|
| 115 |
+
|
| 116 |
+
output_attentions (`bool`, *optional*):
|
| 117 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 118 |
+
tensors for more detail.
|
| 119 |
+
|
| 120 |
+
output_hidden_states (`bool`, *optional*):
|
| 121 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 122 |
+
more detail.
|
| 123 |
+
|
| 124 |
+
return_dict (`bool`, *optional*):
|
| 125 |
+
Whether or not to return a [`~file_utils.ModelOutput`] instead of a plain tuple.
|
| 126 |
+
"""
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
@dataclass
|
| 130 |
+
class BrosSpadeOutput(ModelOutput):
|
| 131 |
+
"""
|
| 132 |
+
Base class for outputs of token classification models.
|
| 133 |
+
|
| 134 |
+
Args:
|
| 135 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` is provided) :
|
| 136 |
+
Classification loss.
|
| 137 |
+
initial_token_logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.num_labels)`):
|
| 138 |
+
Classification scores for entity initial tokens (before SoftMax).
|
| 139 |
+
subsequent_token_logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, sequence_length+1)`):
|
| 140 |
+
Classification scores for entity sequence tokens (before SoftMax).
|
| 141 |
+
hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
|
| 142 |
+
Tuple of `torch.FloatTensor` (one for the output of the embeddings, if the model has an embedding layer, +
|
| 143 |
+
one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.
|
| 144 |
+
|
| 145 |
+
Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.
|
| 146 |
+
attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
|
| 147 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 148 |
+
sequence_length)`.
|
| 149 |
+
|
| 150 |
+
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
| 151 |
+
heads.
|
| 152 |
+
"""
|
| 153 |
+
|
| 154 |
+
loss: Optional[torch.FloatTensor] = None
|
| 155 |
+
initial_token_logits: Optional[torch.FloatTensor] = None
|
| 156 |
+
subsequent_token_logits: Optional[torch.FloatTensor] = None
|
| 157 |
+
hidden_states: Optional[Tuple[torch.FloatTensor]] = None
|
| 158 |
+
attentions: Optional[Tuple[torch.FloatTensor]] = None
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
class BrosPositionalEmbedding1D(nn.Module):
|
| 162 |
+
# Reference: https://github.com/kimiyoung/transformer-xl/blob/master/pytorch/mem_transformer.py#L15
|
| 163 |
+
|
| 164 |
+
def __init__(self, config):
|
| 165 |
+
super(BrosPositionalEmbedding1D, self).__init__()
|
| 166 |
+
|
| 167 |
+
self.dim_bbox_sinusoid_emb_1d = config.dim_bbox_sinusoid_emb_1d
|
| 168 |
+
|
| 169 |
+
inv_freq = 1 / (
|
| 170 |
+
10000 ** (torch.arange(0.0, self.dim_bbox_sinusoid_emb_1d, 2.0) / self.dim_bbox_sinusoid_emb_1d)
|
| 171 |
+
)
|
| 172 |
+
self.register_buffer("inv_freq", inv_freq)
|
| 173 |
+
|
| 174 |
+
def forward(self, pos_seq: torch.Tensor) -> torch.Tensor:
|
| 175 |
+
seq_size = pos_seq.size()
|
| 176 |
+
b1, b2, b3 = seq_size
|
| 177 |
+
sinusoid_inp = pos_seq.view(b1, b2, b3, 1) * self.inv_freq.view(1, 1, 1, self.dim_bbox_sinusoid_emb_1d // 2)
|
| 178 |
+
pos_emb = torch.cat([sinusoid_inp.sin(), sinusoid_inp.cos()], dim=-1)
|
| 179 |
+
return pos_emb
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
class BrosPositionalEmbedding2D(nn.Module):
|
| 183 |
+
def __init__(self, config):
|
| 184 |
+
super(BrosPositionalEmbedding2D, self).__init__()
|
| 185 |
+
|
| 186 |
+
self.dim_bbox = config.dim_bbox
|
| 187 |
+
self.x_pos_emb = BrosPositionalEmbedding1D(config)
|
| 188 |
+
self.y_pos_emb = BrosPositionalEmbedding1D(config)
|
| 189 |
+
|
| 190 |
+
def forward(self, bbox: torch.Tensor) -> torch.Tensor:
|
| 191 |
+
stack = []
|
| 192 |
+
for i in range(self.dim_bbox):
|
| 193 |
+
if i % 2 == 0:
|
| 194 |
+
stack.append(self.x_pos_emb(bbox[..., i]))
|
| 195 |
+
else:
|
| 196 |
+
stack.append(self.y_pos_emb(bbox[..., i]))
|
| 197 |
+
bbox_pos_emb = torch.cat(stack, dim=-1)
|
| 198 |
+
return bbox_pos_emb
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
class BrosBboxEmbeddings(nn.Module):
|
| 202 |
+
def __init__(self, config):
|
| 203 |
+
super(BrosBboxEmbeddings, self).__init__()
|
| 204 |
+
self.bbox_sinusoid_emb = BrosPositionalEmbedding2D(config)
|
| 205 |
+
self.bbox_projection = nn.Linear(config.dim_bbox_sinusoid_emb_2d, config.dim_bbox_projection, bias=False)
|
| 206 |
+
|
| 207 |
+
def forward(self, bbox: torch.Tensor):
|
| 208 |
+
bbox_t = bbox.transpose(0, 1)
|
| 209 |
+
bbox_pos = bbox_t[None, :, :, :] - bbox_t[:, None, :, :]
|
| 210 |
+
bbox_pos_emb = self.bbox_sinusoid_emb(bbox_pos)
|
| 211 |
+
bbox_pos_emb = self.bbox_projection(bbox_pos_emb)
|
| 212 |
+
|
| 213 |
+
return bbox_pos_emb
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
class BrosTextEmbeddings(nn.Module):
|
| 217 |
+
"""Construct the embeddings from word, position and token_type embeddings."""
|
| 218 |
+
|
| 219 |
+
def __init__(self, config):
|
| 220 |
+
super().__init__()
|
| 221 |
+
|
| 222 |
+
self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)
|
| 223 |
+
self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)
|
| 224 |
+
self.token_type_embeddings = nn.Embedding(config.type_vocab_size, config.hidden_size)
|
| 225 |
+
|
| 226 |
+
# self.LayerNorm is not snake-cased to stick with TensorFlow model variable name and be able to load
|
| 227 |
+
# any TensorFlow checkpoint file
|
| 228 |
+
self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 229 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 230 |
+
# position_ids (1, len position emb) is contiguous in memory and exported when serialized
|
| 231 |
+
self.position_embedding_type = getattr(config, "position_embedding_type", "absolute")
|
| 232 |
+
self.register_buffer("position_ids", torch.arange(config.max_position_embeddings).expand((1, -1)))
|
| 233 |
+
self.register_buffer(
|
| 234 |
+
"token_type_ids",
|
| 235 |
+
torch.zeros(
|
| 236 |
+
self.position_ids.size(),
|
| 237 |
+
dtype=torch.long,
|
| 238 |
+
device=self.position_ids.device,
|
| 239 |
+
),
|
| 240 |
+
persistent=False,
|
| 241 |
+
)
|
| 242 |
+
|
| 243 |
+
def forward(
|
| 244 |
+
self,
|
| 245 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 246 |
+
token_type_ids: Optional[torch.Tensor] = None,
|
| 247 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 248 |
+
inputs_embeds: Optional[torch.Tensor] = None,
|
| 249 |
+
past_key_values_length: int = 0,
|
| 250 |
+
) -> torch.Tensor:
|
| 251 |
+
if input_ids is not None:
|
| 252 |
+
input_shape = input_ids.size()
|
| 253 |
+
else:
|
| 254 |
+
input_shape = inputs_embeds.size()[:-1]
|
| 255 |
+
|
| 256 |
+
seq_length = input_shape[1]
|
| 257 |
+
|
| 258 |
+
if position_ids is None:
|
| 259 |
+
position_ids = self.position_ids[:, past_key_values_length : seq_length + past_key_values_length]
|
| 260 |
+
|
| 261 |
+
if token_type_ids is None:
|
| 262 |
+
if hasattr(self, "token_type_ids"):
|
| 263 |
+
buffered_token_type_ids = self.token_type_ids[:, :seq_length]
|
| 264 |
+
buffered_token_type_ids_expanded = buffered_token_type_ids.expand(input_shape[0], seq_length)
|
| 265 |
+
token_type_ids = buffered_token_type_ids_expanded
|
| 266 |
+
else:
|
| 267 |
+
token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=self.position_ids.device)
|
| 268 |
+
|
| 269 |
+
if inputs_embeds is None:
|
| 270 |
+
inputs_embeds = self.word_embeddings(input_ids)
|
| 271 |
+
token_type_embeddings = self.token_type_embeddings(token_type_ids)
|
| 272 |
+
|
| 273 |
+
embeddings = inputs_embeds + token_type_embeddings
|
| 274 |
+
if self.position_embedding_type == "absolute":
|
| 275 |
+
position_embeddings = self.position_embeddings(position_ids)
|
| 276 |
+
embeddings += position_embeddings
|
| 277 |
+
embeddings = self.LayerNorm(embeddings)
|
| 278 |
+
embeddings = self.dropout(embeddings)
|
| 279 |
+
return embeddings
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
class BrosSelfAttention(nn.Module):
|
| 283 |
+
def __init__(self, config):
|
| 284 |
+
super().__init__()
|
| 285 |
+
if config.hidden_size % config.num_attention_heads != 0 and not hasattr(config, "embedding_size"):
|
| 286 |
+
raise ValueError(
|
| 287 |
+
f"The hidden size ({config.hidden_size}) is not a multiple of the number of attention "
|
| 288 |
+
f"heads ({config.num_attention_heads})"
|
| 289 |
+
)
|
| 290 |
+
|
| 291 |
+
self.num_attention_heads = config.num_attention_heads
|
| 292 |
+
self.attention_head_size = int(config.hidden_size / config.num_attention_heads)
|
| 293 |
+
self.all_head_size = self.num_attention_heads * self.attention_head_size
|
| 294 |
+
|
| 295 |
+
self.query = nn.Linear(config.hidden_size, self.all_head_size)
|
| 296 |
+
self.key = nn.Linear(config.hidden_size, self.all_head_size)
|
| 297 |
+
self.value = nn.Linear(config.hidden_size, self.all_head_size)
|
| 298 |
+
|
| 299 |
+
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
|
| 300 |
+
self.position_embedding_type = getattr(config, "position_embedding_type", "absolute")
|
| 301 |
+
if self.position_embedding_type == "relative_key" or self.position_embedding_type == "relative_key_query":
|
| 302 |
+
self.max_position_embeddings = config.max_position_embeddings
|
| 303 |
+
self.distance_embedding = nn.Embedding(2 * config.max_position_embeddings - 1, self.attention_head_size)
|
| 304 |
+
|
| 305 |
+
self.is_decoder = config.is_decoder
|
| 306 |
+
|
| 307 |
+
def transpose_for_scores(self, x: torch.Tensor):
|
| 308 |
+
new_x_shape = x.size()[:-1] + (
|
| 309 |
+
self.num_attention_heads,
|
| 310 |
+
self.attention_head_size,
|
| 311 |
+
)
|
| 312 |
+
x = x.view(*new_x_shape)
|
| 313 |
+
return x.permute(0, 2, 1, 3)
|
| 314 |
+
|
| 315 |
+
def forward(
|
| 316 |
+
self,
|
| 317 |
+
hidden_states: torch.Tensor,
|
| 318 |
+
bbox_pos_emb: torch.Tensor,
|
| 319 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 320 |
+
head_mask: Optional[torch.Tensor] = None,
|
| 321 |
+
encoder_hidden_states: Optional[torch.Tensor] = None,
|
| 322 |
+
encoder_attention_mask: Optional[torch.Tensor] = None,
|
| 323 |
+
past_key_value: Optional[Tuple[Tuple[torch.FloatTensor]]] = None,
|
| 324 |
+
output_attentions: Optional[torch.Tensor] = False,
|
| 325 |
+
) -> Tuple[torch.Tensor]:
|
| 326 |
+
mixed_query_layer = self.query(hidden_states)
|
| 327 |
+
|
| 328 |
+
# If this is instantiated as a cross-attention module, the keys
|
| 329 |
+
# and values come from an encoder; the attention mask needs to be
|
| 330 |
+
# such that the encoder's padding tokens are not attended to.
|
| 331 |
+
is_cross_attention = encoder_hidden_states is not None
|
| 332 |
+
|
| 333 |
+
if is_cross_attention and past_key_value is not None:
|
| 334 |
+
# reuse k,v, cross_attentions
|
| 335 |
+
key_layer = past_key_value[0]
|
| 336 |
+
value_layer = past_key_value[1]
|
| 337 |
+
attention_mask = encoder_attention_mask
|
| 338 |
+
elif is_cross_attention:
|
| 339 |
+
key_layer = self.transpose_for_scores(self.key(encoder_hidden_states))
|
| 340 |
+
value_layer = self.transpose_for_scores(self.value(encoder_hidden_states))
|
| 341 |
+
attention_mask = encoder_attention_mask
|
| 342 |
+
elif past_key_value is not None:
|
| 343 |
+
key_layer = self.transpose_for_scores(self.key(hidden_states))
|
| 344 |
+
value_layer = self.transpose_for_scores(self.value(hidden_states))
|
| 345 |
+
key_layer = torch.cat([past_key_value[0], key_layer], dim=2)
|
| 346 |
+
value_layer = torch.cat([past_key_value[1], value_layer], dim=2)
|
| 347 |
+
else:
|
| 348 |
+
key_layer = self.transpose_for_scores(self.key(hidden_states))
|
| 349 |
+
value_layer = self.transpose_for_scores(self.value(hidden_states))
|
| 350 |
+
|
| 351 |
+
query_layer = self.transpose_for_scores(mixed_query_layer)
|
| 352 |
+
|
| 353 |
+
if self.is_decoder:
|
| 354 |
+
# if cross_attention save Tuple(torch.Tensor, torch.Tensor) of all cross attention key/value_states.
|
| 355 |
+
# Further calls to cross_attention layer can then reuse all cross-attention
|
| 356 |
+
# key/value_states (first "if" case)
|
| 357 |
+
# if uni-directional self-attention (decoder) save Tuple(torch.Tensor, torch.Tensor) of
|
| 358 |
+
# all previous decoder key/value_states. Further calls to uni-directional self-attention
|
| 359 |
+
# can concat previous decoder key/value_states to current projected key/value_states (third "elif" case)
|
| 360 |
+
# if encoder bi-directional self-attention `past_key_value` is always `None`
|
| 361 |
+
past_key_value = (key_layer, value_layer)
|
| 362 |
+
|
| 363 |
+
# Take the dot product between "query" and "key" to get the raw attention scores.
|
| 364 |
+
attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2))
|
| 365 |
+
|
| 366 |
+
if self.position_embedding_type == "relative_key" or self.position_embedding_type == "relative_key_query":
|
| 367 |
+
seq_length = hidden_states.size()[1]
|
| 368 |
+
position_ids_l = torch.arange(seq_length, dtype=torch.long, device=hidden_states.device).view(-1, 1)
|
| 369 |
+
position_ids_r = torch.arange(seq_length, dtype=torch.long, device=hidden_states.device).view(1, -1)
|
| 370 |
+
distance = position_ids_l - position_ids_r
|
| 371 |
+
positional_embedding = self.distance_embedding(distance + self.max_position_embeddings - 1)
|
| 372 |
+
positional_embedding = positional_embedding.to(dtype=query_layer.dtype) # fp16 compatibility
|
| 373 |
+
|
| 374 |
+
if self.position_embedding_type == "relative_key":
|
| 375 |
+
relative_position_scores = torch.einsum("bhld,lrd->bhlr", query_layer, positional_embedding)
|
| 376 |
+
attention_scores = attention_scores + relative_position_scores
|
| 377 |
+
elif self.position_embedding_type == "relative_key_query":
|
| 378 |
+
relative_position_scores_query = torch.einsum("bhld,lrd->bhlr", query_layer, positional_embedding)
|
| 379 |
+
relative_position_scores_key = torch.einsum("bhrd,lrd->bhlr", key_layer, positional_embedding)
|
| 380 |
+
|
| 381 |
+
attention_scores = attention_scores + relative_position_scores_query + relative_position_scores_key
|
| 382 |
+
|
| 383 |
+
# bbox positional encoding
|
| 384 |
+
batch_size, n_head, seq_length, d_head = query_layer.shape
|
| 385 |
+
bbox_pos_emb = bbox_pos_emb.view(seq_length, seq_length, batch_size, d_head)
|
| 386 |
+
bbox_pos_emb = bbox_pos_emb.permute([2, 0, 1, 3])
|
| 387 |
+
bbox_pos_scores = torch.einsum("bnid,bijd->bnij", (query_layer, bbox_pos_emb))
|
| 388 |
+
|
| 389 |
+
attention_scores = attention_scores + bbox_pos_scores
|
| 390 |
+
|
| 391 |
+
attention_scores = attention_scores / math.sqrt(self.attention_head_size)
|
| 392 |
+
if attention_mask is not None:
|
| 393 |
+
# Apply the attention mask is (precomputed for all layers in BrosModel forward() function)
|
| 394 |
+
attention_scores = attention_scores + attention_mask
|
| 395 |
+
|
| 396 |
+
# Normalize the attention scores to probabilities.
|
| 397 |
+
attention_probs = nn.Softmax(dim=-1)(attention_scores)
|
| 398 |
+
|
| 399 |
+
# This is actually dropping out entire tokens to attend to, which might
|
| 400 |
+
# seem a bit unusual, but is taken from the original Transformer paper.
|
| 401 |
+
attention_probs = self.dropout(attention_probs)
|
| 402 |
+
|
| 403 |
+
# Mask heads if we want to
|
| 404 |
+
if head_mask is not None:
|
| 405 |
+
attention_probs = attention_probs * head_mask
|
| 406 |
+
|
| 407 |
+
context_layer = torch.matmul(attention_probs, value_layer)
|
| 408 |
+
|
| 409 |
+
context_layer = context_layer.permute(0, 2, 1, 3).contiguous()
|
| 410 |
+
new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,)
|
| 411 |
+
context_layer = context_layer.view(*new_context_layer_shape)
|
| 412 |
+
|
| 413 |
+
outputs = (context_layer, attention_probs) if output_attentions else (context_layer,)
|
| 414 |
+
|
| 415 |
+
if self.is_decoder:
|
| 416 |
+
outputs = outputs + (past_key_value,)
|
| 417 |
+
return outputs
|
| 418 |
+
|
| 419 |
+
|
| 420 |
+
# Copied from transformers.models.bert.modeling_bert.BertSelfOutput with Bert->Bros
|
| 421 |
+
class BrosSelfOutput(nn.Module):
|
| 422 |
+
def __init__(self, config):
|
| 423 |
+
super().__init__()
|
| 424 |
+
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
|
| 425 |
+
self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 426 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 427 |
+
|
| 428 |
+
def forward(self, hidden_states: torch.Tensor, input_tensor: torch.Tensor) -> torch.Tensor:
|
| 429 |
+
hidden_states = self.dense(hidden_states)
|
| 430 |
+
hidden_states = self.dropout(hidden_states)
|
| 431 |
+
hidden_states = self.LayerNorm(hidden_states + input_tensor)
|
| 432 |
+
return hidden_states
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
class BrosAttention(nn.Module):
|
| 436 |
+
def __init__(self, config):
|
| 437 |
+
super().__init__()
|
| 438 |
+
self.self = BrosSelfAttention(config)
|
| 439 |
+
self.output = BrosSelfOutput(config)
|
| 440 |
+
self.pruned_heads = set()
|
| 441 |
+
|
| 442 |
+
def prune_heads(self, heads):
|
| 443 |
+
if len(heads) == 0:
|
| 444 |
+
return
|
| 445 |
+
heads, index = find_pruneable_heads_and_indices(
|
| 446 |
+
heads,
|
| 447 |
+
self.self.num_attention_heads,
|
| 448 |
+
self.self.attention_head_size,
|
| 449 |
+
self.pruned_heads,
|
| 450 |
+
)
|
| 451 |
+
|
| 452 |
+
# Prune linear layers
|
| 453 |
+
self.self.query = prune_linear_layer(self.self.query, index)
|
| 454 |
+
self.self.key = prune_linear_layer(self.self.key, index)
|
| 455 |
+
self.self.value = prune_linear_layer(self.self.value, index)
|
| 456 |
+
self.output.dense = prune_linear_layer(self.output.dense, index, dim=1)
|
| 457 |
+
|
| 458 |
+
# Update hyper params and store pruned heads
|
| 459 |
+
self.self.num_attention_heads = self.self.num_attention_heads - len(heads)
|
| 460 |
+
self.self.all_head_size = self.self.attention_head_size * self.self.num_attention_heads
|
| 461 |
+
self.pruned_heads = self.pruned_heads.union(heads)
|
| 462 |
+
|
| 463 |
+
def forward(
|
| 464 |
+
self,
|
| 465 |
+
hidden_states: torch.Tensor,
|
| 466 |
+
bbox_pos_emb: torch.Tensor,
|
| 467 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 468 |
+
head_mask: Optional[torch.Tensor] = None,
|
| 469 |
+
encoder_hidden_states: Optional[torch.Tensor] = None,
|
| 470 |
+
encoder_attention_mask: Optional[torch.Tensor] = None,
|
| 471 |
+
past_key_value: Optional[Tuple[Tuple[torch.FloatTensor]]] = None,
|
| 472 |
+
output_attentions: Optional[bool] = False,
|
| 473 |
+
) -> Tuple[torch.Tensor]:
|
| 474 |
+
self_outputs = self.self(
|
| 475 |
+
hidden_states=hidden_states,
|
| 476 |
+
bbox_pos_emb=bbox_pos_emb,
|
| 477 |
+
attention_mask=attention_mask,
|
| 478 |
+
head_mask=head_mask,
|
| 479 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 480 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 481 |
+
past_key_value=past_key_value,
|
| 482 |
+
output_attentions=output_attentions,
|
| 483 |
+
)
|
| 484 |
+
attention_output = self.output(self_outputs[0], hidden_states)
|
| 485 |
+
outputs = (attention_output,) + self_outputs[1:] # add attentions if we output them
|
| 486 |
+
return outputs
|
| 487 |
+
|
| 488 |
+
|
| 489 |
+
# Copied from transformers.models.bert.modeling_bert.BertIntermediate with Bert->Bros
|
| 490 |
+
class BrosIntermediate(nn.Module):
|
| 491 |
+
def __init__(self, config):
|
| 492 |
+
super().__init__()
|
| 493 |
+
self.dense = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 494 |
+
if isinstance(config.hidden_act, str):
|
| 495 |
+
self.intermediate_act_fn = ACT2FN[config.hidden_act]
|
| 496 |
+
else:
|
| 497 |
+
self.intermediate_act_fn = config.hidden_act
|
| 498 |
+
|
| 499 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 500 |
+
hidden_states = self.dense(hidden_states)
|
| 501 |
+
hidden_states = self.intermediate_act_fn(hidden_states)
|
| 502 |
+
return hidden_states
|
| 503 |
+
|
| 504 |
+
|
| 505 |
+
class BrosOutput(nn.Module):
|
| 506 |
+
def __init__(self, config):
|
| 507 |
+
super().__init__()
|
| 508 |
+
self.dense = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 509 |
+
self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 510 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 511 |
+
|
| 512 |
+
def forward(self, hidden_states: torch.Tensor, input_tensor: torch.Tensor) -> torch.Tensor:
|
| 513 |
+
hidden_states = self.dense(hidden_states)
|
| 514 |
+
hidden_states = self.dropout(hidden_states)
|
| 515 |
+
hidden_states = self.LayerNorm(hidden_states + input_tensor)
|
| 516 |
+
return hidden_states
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
class BrosLayer(nn.Module):
|
| 520 |
+
def __init__(self, config):
|
| 521 |
+
super().__init__()
|
| 522 |
+
self.chunk_size_feed_forward = config.chunk_size_feed_forward
|
| 523 |
+
self.seq_len_dim = 1
|
| 524 |
+
self.attention = BrosAttention(config)
|
| 525 |
+
self.is_decoder = config.is_decoder
|
| 526 |
+
self.add_cross_attention = config.add_cross_attention
|
| 527 |
+
if self.add_cross_attention:
|
| 528 |
+
if not self.is_decoder:
|
| 529 |
+
raise Exception(f"{self} should be used as a decoder model if cross attention is added")
|
| 530 |
+
self.crossattention = BrosAttention(config)
|
| 531 |
+
self.intermediate = BrosIntermediate(config)
|
| 532 |
+
self.output = BrosOutput(config)
|
| 533 |
+
|
| 534 |
+
def forward(
|
| 535 |
+
self,
|
| 536 |
+
hidden_states: torch.Tensor,
|
| 537 |
+
bbox_pos_emb: torch.Tensor,
|
| 538 |
+
attention_mask: Optional[torch.FloatTensor] = None,
|
| 539 |
+
head_mask: Optional[torch.FloatTensor] = None,
|
| 540 |
+
encoder_hidden_states: Optional[torch.FloatTensor] = None,
|
| 541 |
+
encoder_attention_mask: Optional[torch.FloatTensor] = None,
|
| 542 |
+
past_key_value: Optional[Tuple[Tuple[torch.FloatTensor]]] = None,
|
| 543 |
+
output_attentions: Optional[bool] = False,
|
| 544 |
+
) -> Tuple[torch.Tensor]:
|
| 545 |
+
# decoder uni-directional self-attention cached key/values tuple is at positions 1,2
|
| 546 |
+
self_attn_past_key_value = past_key_value[:2] if past_key_value is not None else None
|
| 547 |
+
self_attention_outputs = self.attention(
|
| 548 |
+
hidden_states,
|
| 549 |
+
bbox_pos_emb=bbox_pos_emb,
|
| 550 |
+
attention_mask=attention_mask,
|
| 551 |
+
head_mask=head_mask,
|
| 552 |
+
output_attentions=output_attentions,
|
| 553 |
+
past_key_value=self_attn_past_key_value,
|
| 554 |
+
)
|
| 555 |
+
attention_output = self_attention_outputs[0]
|
| 556 |
+
|
| 557 |
+
# if decoder, the last output is tuple of self-attn cache
|
| 558 |
+
if self.is_decoder:
|
| 559 |
+
outputs = self_attention_outputs[1:-1]
|
| 560 |
+
present_key_value = self_attention_outputs[-1]
|
| 561 |
+
else:
|
| 562 |
+
outputs = self_attention_outputs[1:] # add self attentions if we output attention weights
|
| 563 |
+
|
| 564 |
+
cross_attn_present_key_value = None
|
| 565 |
+
if self.is_decoder and encoder_hidden_states is not None:
|
| 566 |
+
if hasattr(self, "crossattention"):
|
| 567 |
+
raise Exception(
|
| 568 |
+
f"If `encoder_hidden_states` are passed, {self} has to be instantiated with cross-attention layers by setting `config.add_cross_attention=True`"
|
| 569 |
+
)
|
| 570 |
+
|
| 571 |
+
# cross_attn cached key/values tuple is at positions 3,4 of past_key_value tuple
|
| 572 |
+
cross_attn_past_key_value = past_key_value[-2:] if past_key_value is not None else None
|
| 573 |
+
cross_attention_outputs = self.crossattention(
|
| 574 |
+
attention_output,
|
| 575 |
+
attention_mask,
|
| 576 |
+
head_mask,
|
| 577 |
+
encoder_hidden_states,
|
| 578 |
+
encoder_attention_mask,
|
| 579 |
+
cross_attn_past_key_value,
|
| 580 |
+
output_attentions,
|
| 581 |
+
)
|
| 582 |
+
attention_output = cross_attention_outputs[0]
|
| 583 |
+
outputs = outputs + cross_attention_outputs[1:-1] # add cross attentions if we output attention weights
|
| 584 |
+
|
| 585 |
+
# add cross-attn cache to positions 3,4 of present_key_value tuple
|
| 586 |
+
cross_attn_present_key_value = cross_attention_outputs[-1]
|
| 587 |
+
present_key_value = present_key_value + cross_attn_present_key_value
|
| 588 |
+
|
| 589 |
+
layer_output = apply_chunking_to_forward(
|
| 590 |
+
self.feed_forward_chunk,
|
| 591 |
+
self.chunk_size_feed_forward,
|
| 592 |
+
self.seq_len_dim,
|
| 593 |
+
attention_output,
|
| 594 |
+
)
|
| 595 |
+
outputs = (layer_output,) + outputs
|
| 596 |
+
|
| 597 |
+
# if decoder, return the attn key/values as the last output
|
| 598 |
+
if self.is_decoder:
|
| 599 |
+
outputs = outputs + (present_key_value,)
|
| 600 |
+
|
| 601 |
+
return outputs
|
| 602 |
+
|
| 603 |
+
def feed_forward_chunk(self, attention_output):
|
| 604 |
+
intermediate_output = self.intermediate(attention_output)
|
| 605 |
+
layer_output = self.output(intermediate_output, attention_output)
|
| 606 |
+
return layer_output
|
| 607 |
+
|
| 608 |
+
|
| 609 |
+
class BrosEncoder(nn.Module):
|
| 610 |
+
def __init__(self, config):
|
| 611 |
+
super().__init__()
|
| 612 |
+
self.config = config
|
| 613 |
+
self.layer = nn.ModuleList([BrosLayer(config) for _ in range(config.num_hidden_layers)])
|
| 614 |
+
|
| 615 |
+
def forward(
|
| 616 |
+
self,
|
| 617 |
+
hidden_states: torch.Tensor,
|
| 618 |
+
bbox_pos_emb: torch.Tensor,
|
| 619 |
+
attention_mask: Optional[torch.FloatTensor] = None,
|
| 620 |
+
head_mask: Optional[torch.FloatTensor] = None,
|
| 621 |
+
encoder_hidden_states: Optional[torch.FloatTensor] = None,
|
| 622 |
+
encoder_attention_mask: Optional[torch.FloatTensor] = None,
|
| 623 |
+
past_key_values: Optional[Tuple[Tuple[torch.FloatTensor]]] = None,
|
| 624 |
+
use_cache: Optional[bool] = None,
|
| 625 |
+
output_attentions: Optional[bool] = False,
|
| 626 |
+
output_hidden_states: Optional[bool] = False,
|
| 627 |
+
return_dict: Optional[bool] = True,
|
| 628 |
+
) -> Union[Tuple[torch.Tensor], BaseModelOutputWithPastAndCrossAttentions]:
|
| 629 |
+
all_hidden_states = () if output_hidden_states else None
|
| 630 |
+
all_self_attentions = () if output_attentions else None
|
| 631 |
+
all_cross_attentions = () if output_attentions and self.config.add_cross_attention else None
|
| 632 |
+
|
| 633 |
+
next_decoder_cache = () if use_cache else None
|
| 634 |
+
for i, layer_module in enumerate(self.layer):
|
| 635 |
+
if output_hidden_states:
|
| 636 |
+
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 637 |
+
|
| 638 |
+
layer_head_mask = head_mask[i] if head_mask is not None else None
|
| 639 |
+
past_key_value = past_key_values[i] if past_key_values is not None else None
|
| 640 |
+
|
| 641 |
+
if getattr(self.config, "gradient_checkpointing", False) and self.training:
|
| 642 |
+
if use_cache:
|
| 643 |
+
logger.warning(
|
| 644 |
+
"`use_cache=True` is incompatible with `config.gradient_checkpointing=True`. Setting "
|
| 645 |
+
"`use_cache=False`..."
|
| 646 |
+
)
|
| 647 |
+
use_cache = False
|
| 648 |
+
layer_outputs = self._gradient_checkpointing_func(
|
| 649 |
+
layer_module.__call__,
|
| 650 |
+
hidden_states,
|
| 651 |
+
bbox_pos_emb,
|
| 652 |
+
attention_mask,
|
| 653 |
+
layer_head_mask,
|
| 654 |
+
encoder_hidden_states,
|
| 655 |
+
encoder_attention_mask,
|
| 656 |
+
output_attentions,
|
| 657 |
+
)
|
| 658 |
+
else:
|
| 659 |
+
layer_outputs = layer_module(
|
| 660 |
+
hidden_states=hidden_states,
|
| 661 |
+
bbox_pos_emb=bbox_pos_emb,
|
| 662 |
+
attention_mask=attention_mask,
|
| 663 |
+
head_mask=layer_head_mask,
|
| 664 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 665 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 666 |
+
past_key_value=past_key_value,
|
| 667 |
+
output_attentions=output_attentions,
|
| 668 |
+
)
|
| 669 |
+
|
| 670 |
+
hidden_states = layer_outputs[0]
|
| 671 |
+
if use_cache:
|
| 672 |
+
next_decoder_cache += (layer_outputs[-1],)
|
| 673 |
+
if output_attentions:
|
| 674 |
+
all_self_attentions = all_self_attentions + (layer_outputs[1],)
|
| 675 |
+
if self.config.add_cross_attention:
|
| 676 |
+
all_cross_attentions = all_cross_attentions + (layer_outputs[2],)
|
| 677 |
+
|
| 678 |
+
if output_hidden_states:
|
| 679 |
+
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 680 |
+
|
| 681 |
+
if not return_dict:
|
| 682 |
+
return tuple(
|
| 683 |
+
v
|
| 684 |
+
for v in [
|
| 685 |
+
hidden_states,
|
| 686 |
+
next_decoder_cache,
|
| 687 |
+
all_hidden_states,
|
| 688 |
+
all_self_attentions,
|
| 689 |
+
all_cross_attentions,
|
| 690 |
+
]
|
| 691 |
+
if v is not None
|
| 692 |
+
)
|
| 693 |
+
return BaseModelOutputWithPastAndCrossAttentions(
|
| 694 |
+
last_hidden_state=hidden_states,
|
| 695 |
+
past_key_values=next_decoder_cache,
|
| 696 |
+
hidden_states=all_hidden_states,
|
| 697 |
+
attentions=all_self_attentions,
|
| 698 |
+
cross_attentions=all_cross_attentions,
|
| 699 |
+
)
|
| 700 |
+
|
| 701 |
+
|
| 702 |
+
# Copied from transformers.models.bert.modeling_bert.BertPooler with Bert->Bros
|
| 703 |
+
class BrosPooler(nn.Module):
|
| 704 |
+
def __init__(self, config):
|
| 705 |
+
super().__init__()
|
| 706 |
+
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
|
| 707 |
+
self.activation = nn.Tanh()
|
| 708 |
+
|
| 709 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 710 |
+
# We "pool" the model by simply taking the hidden state corresponding
|
| 711 |
+
# to the first token.
|
| 712 |
+
first_token_tensor = hidden_states[:, 0]
|
| 713 |
+
pooled_output = self.dense(first_token_tensor)
|
| 714 |
+
pooled_output = self.activation(pooled_output)
|
| 715 |
+
return pooled_output
|
| 716 |
+
|
| 717 |
+
|
| 718 |
+
class BrosRelationExtractor(nn.Module):
|
| 719 |
+
def __init__(self, config):
|
| 720 |
+
super().__init__()
|
| 721 |
+
self.n_relations = config.n_relations
|
| 722 |
+
self.backbone_hidden_size = config.hidden_size
|
| 723 |
+
self.head_hidden_size = config.hidden_size
|
| 724 |
+
self.classifier_dropout_prob = config.classifier_dropout_prob
|
| 725 |
+
|
| 726 |
+
self.drop = nn.Dropout(self.classifier_dropout_prob)
|
| 727 |
+
self.query = nn.Linear(self.backbone_hidden_size, self.n_relations * self.head_hidden_size)
|
| 728 |
+
|
| 729 |
+
self.key = nn.Linear(self.backbone_hidden_size, self.n_relations * self.head_hidden_size)
|
| 730 |
+
|
| 731 |
+
self.dummy_node = nn.Parameter(torch.zeros(1, self.backbone_hidden_size))
|
| 732 |
+
|
| 733 |
+
def forward(self, query_layer: torch.Tensor, key_layer: torch.Tensor):
|
| 734 |
+
query_layer = self.query(self.drop(query_layer))
|
| 735 |
+
|
| 736 |
+
dummy_vec = self.dummy_node.unsqueeze(0).repeat(1, key_layer.size(1), 1)
|
| 737 |
+
key_layer = torch.cat([key_layer, dummy_vec], axis=0)
|
| 738 |
+
key_layer = self.key(self.drop(key_layer))
|
| 739 |
+
|
| 740 |
+
query_layer = query_layer.view(
|
| 741 |
+
query_layer.size(0), query_layer.size(1), self.n_relations, self.head_hidden_size
|
| 742 |
+
)
|
| 743 |
+
key_layer = key_layer.view(key_layer.size(0), key_layer.size(1), self.n_relations, self.head_hidden_size)
|
| 744 |
+
|
| 745 |
+
relation_score = torch.matmul(
|
| 746 |
+
query_layer.permute(2, 1, 0, 3), key_layer.permute(2, 1, 3, 0)
|
| 747 |
+
) # equivalent to torch.einsum("ibnd,jbnd->nbij", (query_layer, key_layer))
|
| 748 |
+
|
| 749 |
+
return relation_score
|
| 750 |
+
|
| 751 |
+
|
| 752 |
+
class BrosPreTrainedModel(PreTrainedModel):
|
| 753 |
+
"""
|
| 754 |
+
An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained
|
| 755 |
+
models.
|
| 756 |
+
"""
|
| 757 |
+
|
| 758 |
+
config_class = BrosConfig
|
| 759 |
+
base_model_prefix = "bros"
|
| 760 |
+
|
| 761 |
+
def _init_weights(self, module):
|
| 762 |
+
"""Initialize the weights"""
|
| 763 |
+
if isinstance(module, nn.Linear):
|
| 764 |
+
# Slightly different from the TF version which uses truncated_normal for initialization
|
| 765 |
+
# cf https://github.com/pytorch/pytorch/pull/5617
|
| 766 |
+
module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
|
| 767 |
+
if module.bias is not None:
|
| 768 |
+
module.bias.data.zero_()
|
| 769 |
+
elif isinstance(module, nn.Embedding):
|
| 770 |
+
module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
|
| 771 |
+
if module.padding_idx is not None:
|
| 772 |
+
module.weight.data[module.padding_idx].zero_()
|
| 773 |
+
elif isinstance(module, nn.LayerNorm):
|
| 774 |
+
module.bias.data.zero_()
|
| 775 |
+
module.weight.data.fill_(1.0)
|
| 776 |
+
|
| 777 |
+
|
| 778 |
+
@add_start_docstrings(
|
| 779 |
+
"The bare Bros Model transformer outputting raw hidden-states without any specific head on top.",
|
| 780 |
+
BROS_START_DOCSTRING,
|
| 781 |
+
)
|
| 782 |
+
class BrosModel(BrosPreTrainedModel):
|
| 783 |
+
def __init__(self, config, add_pooling_layer=True):
|
| 784 |
+
super().__init__(config)
|
| 785 |
+
self.config = config
|
| 786 |
+
|
| 787 |
+
self.embeddings = BrosTextEmbeddings(config)
|
| 788 |
+
self.bbox_embeddings = BrosBboxEmbeddings(config)
|
| 789 |
+
self.encoder = BrosEncoder(config)
|
| 790 |
+
|
| 791 |
+
self.pooler = BrosPooler(config) if add_pooling_layer else None
|
| 792 |
+
|
| 793 |
+
self.init_weights()
|
| 794 |
+
|
| 795 |
+
def get_input_embeddings(self):
|
| 796 |
+
return self.embeddings.word_embeddings
|
| 797 |
+
|
| 798 |
+
def set_input_embeddings(self, value):
|
| 799 |
+
self.embeddings.word_embeddings = value
|
| 800 |
+
|
| 801 |
+
def _prune_heads(self, heads_to_prune):
|
| 802 |
+
"""
|
| 803 |
+
Prunes heads of the model. heads_to_prune: dict of {layer_num: list of heads to prune in this layer} See base
|
| 804 |
+
class PreTrainedModel
|
| 805 |
+
"""
|
| 806 |
+
for layer, heads in heads_to_prune.items():
|
| 807 |
+
self.encoder.layer[layer].attention.prune_heads(heads)
|
| 808 |
+
|
| 809 |
+
@add_start_docstrings_to_model_forward(BROS_INPUTS_DOCSTRING.format("batch_size, sequence_length"))
|
| 810 |
+
@replace_return_docstrings(output_type=BaseModelOutputWithPoolingAndCrossAttentions, config_class=_CONFIG_FOR_DOC)
|
| 811 |
+
def forward(
|
| 812 |
+
self,
|
| 813 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 814 |
+
bbox: Optional[torch.Tensor] = None,
|
| 815 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 816 |
+
token_type_ids: Optional[torch.Tensor] = None,
|
| 817 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 818 |
+
head_mask: Optional[torch.Tensor] = None,
|
| 819 |
+
inputs_embeds: Optional[torch.Tensor] = None,
|
| 820 |
+
encoder_hidden_states: Optional[torch.Tensor] = None,
|
| 821 |
+
encoder_attention_mask: Optional[torch.Tensor] = None,
|
| 822 |
+
past_key_values: Optional[List[torch.FloatTensor]] = None,
|
| 823 |
+
use_cache: Optional[bool] = None,
|
| 824 |
+
output_attentions: Optional[bool] = None,
|
| 825 |
+
output_hidden_states: Optional[bool] = None,
|
| 826 |
+
return_dict: Optional[bool] = None,
|
| 827 |
+
) -> Union[Tuple[torch.Tensor], BaseModelOutputWithPoolingAndCrossAttentions]:
|
| 828 |
+
r"""
|
| 829 |
+
Returns:
|
| 830 |
+
|
| 831 |
+
Examples:
|
| 832 |
+
|
| 833 |
+
```python
|
| 834 |
+
>>> import torch
|
| 835 |
+
>>> from transformers import BrosProcessor, BrosModel
|
| 836 |
+
|
| 837 |
+
>>> processor = BrosProcessor.from_pretrained("jinho8345/bros-base-uncased")
|
| 838 |
+
|
| 839 |
+
>>> model = BrosModel.from_pretrained("jinho8345/bros-base-uncased")
|
| 840 |
+
|
| 841 |
+
>>> encoding = processor("Hello, my dog is cute", add_special_tokens=False, return_tensors="pt")
|
| 842 |
+
>>> bbox = torch.tensor([[[0, 0, 1, 1]]]).repeat(1, encoding["input_ids"].shape[-1], 1)
|
| 843 |
+
>>> encoding["bbox"] = bbox
|
| 844 |
+
|
| 845 |
+
>>> outputs = model(**encoding)
|
| 846 |
+
>>> last_hidden_states = outputs.last_hidden_state
|
| 847 |
+
```"""
|
| 848 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 849 |
+
output_hidden_states = (
|
| 850 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 851 |
+
)
|
| 852 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 853 |
+
|
| 854 |
+
if self.config.is_decoder:
|
| 855 |
+
use_cache = use_cache if use_cache is not None else self.config.use_cache
|
| 856 |
+
else:
|
| 857 |
+
use_cache = False
|
| 858 |
+
|
| 859 |
+
if input_ids is not None and inputs_embeds is not None:
|
| 860 |
+
raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
|
| 861 |
+
elif input_ids is not None:
|
| 862 |
+
input_shape = input_ids.size()
|
| 863 |
+
elif inputs_embeds is not None:
|
| 864 |
+
input_shape = inputs_embeds.size()[:-1]
|
| 865 |
+
else:
|
| 866 |
+
raise ValueError("You have to specify either input_ids or inputs_embeds")
|
| 867 |
+
|
| 868 |
+
if bbox is None:
|
| 869 |
+
raise ValueError("You have to specify bbox")
|
| 870 |
+
|
| 871 |
+
batch_size, seq_length = input_shape
|
| 872 |
+
device = input_ids.device if input_ids is not None else inputs_embeds.device
|
| 873 |
+
|
| 874 |
+
# past_key_values_length
|
| 875 |
+
past_key_values_length = past_key_values[0][0].shape[2] if past_key_values is not None else 0
|
| 876 |
+
|
| 877 |
+
if attention_mask is None:
|
| 878 |
+
attention_mask = torch.ones(input_shape, device=device)
|
| 879 |
+
|
| 880 |
+
if token_type_ids is None:
|
| 881 |
+
if hasattr(self.embeddings, "token_type_ids"):
|
| 882 |
+
buffered_token_type_ids = self.embeddings.token_type_ids[:, :seq_length]
|
| 883 |
+
buffered_token_type_ids_expanded = buffered_token_type_ids.expand(batch_size, seq_length)
|
| 884 |
+
token_type_ids = buffered_token_type_ids_expanded
|
| 885 |
+
else:
|
| 886 |
+
token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=device)
|
| 887 |
+
|
| 888 |
+
# We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length]
|
| 889 |
+
# ourselves in which case we just need to make it broadcastable to all heads.
|
| 890 |
+
extended_attention_mask: torch.Tensor = self.get_extended_attention_mask(attention_mask, input_shape, device)
|
| 891 |
+
|
| 892 |
+
# If a 2D or 3D attention mask is provided for the cross-attention
|
| 893 |
+
# we need to make broadcastable to [batch_size, num_heads, seq_length, seq_length]
|
| 894 |
+
if self.config.is_decoder and encoder_hidden_states is not None:
|
| 895 |
+
encoder_batch_size, encoder_sequence_length, _ = encoder_hidden_states.size()
|
| 896 |
+
encoder_hidden_shape = (encoder_batch_size, encoder_sequence_length)
|
| 897 |
+
if encoder_attention_mask is None:
|
| 898 |
+
encoder_attention_mask = torch.ones(encoder_hidden_shape, device=device)
|
| 899 |
+
encoder_extended_attention_mask = self.invert_attention_mask(encoder_attention_mask)
|
| 900 |
+
else:
|
| 901 |
+
encoder_extended_attention_mask = None
|
| 902 |
+
|
| 903 |
+
# Prepare head mask if needed
|
| 904 |
+
# 1.0 in head_mask indicate we keep the head
|
| 905 |
+
# attention_probs has shape bsz x n_heads x N x N
|
| 906 |
+
# input head_mask has shape [num_heads] or [num_hidden_layers x num_heads]
|
| 907 |
+
# and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length]
|
| 908 |
+
head_mask = self.get_head_mask(head_mask, self.config.num_hidden_layers)
|
| 909 |
+
|
| 910 |
+
embedding_output = self.embeddings(
|
| 911 |
+
input_ids=input_ids,
|
| 912 |
+
position_ids=position_ids,
|
| 913 |
+
token_type_ids=token_type_ids,
|
| 914 |
+
inputs_embeds=inputs_embeds,
|
| 915 |
+
past_key_values_length=past_key_values_length,
|
| 916 |
+
)
|
| 917 |
+
|
| 918 |
+
# if bbox has 2 points (4 float tensors) per token, convert it to 4 points (8 float tensors) per token
|
| 919 |
+
if bbox.shape[-1] == 4:
|
| 920 |
+
bbox = bbox[:, :, [0, 1, 2, 1, 2, 3, 0, 3]]
|
| 921 |
+
scaled_bbox = bbox * self.config.bbox_scale
|
| 922 |
+
bbox_position_embeddings = self.bbox_embeddings(scaled_bbox)
|
| 923 |
+
|
| 924 |
+
encoder_outputs = self.encoder(
|
| 925 |
+
embedding_output,
|
| 926 |
+
bbox_pos_emb=bbox_position_embeddings,
|
| 927 |
+
attention_mask=extended_attention_mask,
|
| 928 |
+
head_mask=head_mask,
|
| 929 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 930 |
+
encoder_attention_mask=encoder_extended_attention_mask,
|
| 931 |
+
past_key_values=past_key_values,
|
| 932 |
+
use_cache=use_cache,
|
| 933 |
+
output_attentions=output_attentions,
|
| 934 |
+
output_hidden_states=output_hidden_states,
|
| 935 |
+
return_dict=return_dict,
|
| 936 |
+
)
|
| 937 |
+
sequence_output = encoder_outputs[0]
|
| 938 |
+
pooled_output = self.pooler(sequence_output) if self.pooler is not None else None
|
| 939 |
+
|
| 940 |
+
if not return_dict:
|
| 941 |
+
return (sequence_output, pooled_output) + encoder_outputs[1:]
|
| 942 |
+
|
| 943 |
+
return BaseModelOutputWithPoolingAndCrossAttentions(
|
| 944 |
+
last_hidden_state=sequence_output,
|
| 945 |
+
pooler_output=pooled_output,
|
| 946 |
+
past_key_values=encoder_outputs.past_key_values,
|
| 947 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 948 |
+
attentions=encoder_outputs.attentions,
|
| 949 |
+
cross_attentions=encoder_outputs.cross_attentions,
|
| 950 |
+
)
|
| 951 |
+
|
| 952 |
+
|
| 953 |
+
@add_start_docstrings(
|
| 954 |
+
"""
|
| 955 |
+
Bros Model with a token classification head on top (a linear layer on top of the hidden-states output) e.g. for
|
| 956 |
+
Named-Entity-Recognition (NER) tasks.
|
| 957 |
+
""",
|
| 958 |
+
BROS_START_DOCSTRING,
|
| 959 |
+
)
|
| 960 |
+
class BrosForTokenClassification(BrosPreTrainedModel):
|
| 961 |
+
_keys_to_ignore_on_load_unexpected = [r"pooler"]
|
| 962 |
+
|
| 963 |
+
def __init__(self, config):
|
| 964 |
+
super().__init__(config)
|
| 965 |
+
self.num_labels = config.num_labels
|
| 966 |
+
|
| 967 |
+
self.bros = BrosModel(config)
|
| 968 |
+
classifier_dropout = (
|
| 969 |
+
config.classifier_dropout if hasattr(config, "classifier_dropout") else config.hidden_dropout_prob
|
| 970 |
+
)
|
| 971 |
+
self.dropout = nn.Dropout(classifier_dropout)
|
| 972 |
+
self.classifier = nn.Linear(config.hidden_size, config.num_labels)
|
| 973 |
+
|
| 974 |
+
self.init_weights()
|
| 975 |
+
|
| 976 |
+
@add_start_docstrings_to_model_forward(BROS_INPUTS_DOCSTRING.format("batch_size, sequence_length"))
|
| 977 |
+
@replace_return_docstrings(output_type=TokenClassifierOutput, config_class=_CONFIG_FOR_DOC)
|
| 978 |
+
def forward(
|
| 979 |
+
self,
|
| 980 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 981 |
+
bbox: Optional[torch.Tensor] = None,
|
| 982 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 983 |
+
bbox_first_token_mask: Optional[torch.Tensor] = None,
|
| 984 |
+
token_type_ids: Optional[torch.Tensor] = None,
|
| 985 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 986 |
+
head_mask: Optional[torch.Tensor] = None,
|
| 987 |
+
inputs_embeds: Optional[torch.Tensor] = None,
|
| 988 |
+
labels: Optional[torch.Tensor] = None,
|
| 989 |
+
output_attentions: Optional[bool] = None,
|
| 990 |
+
output_hidden_states: Optional[bool] = None,
|
| 991 |
+
return_dict: Optional[bool] = None,
|
| 992 |
+
) -> Union[Tuple[torch.Tensor], TokenClassifierOutput]:
|
| 993 |
+
r"""
|
| 994 |
+
|
| 995 |
+
Returns:
|
| 996 |
+
|
| 997 |
+
Examples:
|
| 998 |
+
|
| 999 |
+
```python
|
| 1000 |
+
>>> import torch
|
| 1001 |
+
>>> from transformers import BrosProcessor, BrosForTokenClassification
|
| 1002 |
+
|
| 1003 |
+
>>> processor = BrosProcessor.from_pretrained("jinho8345/bros-base-uncased")
|
| 1004 |
+
|
| 1005 |
+
>>> model = BrosForTokenClassification.from_pretrained("jinho8345/bros-base-uncased")
|
| 1006 |
+
|
| 1007 |
+
>>> encoding = processor("Hello, my dog is cute", add_special_tokens=False, return_tensors="pt")
|
| 1008 |
+
>>> bbox = torch.tensor([[[0, 0, 1, 1]]]).repeat(1, encoding["input_ids"].shape[-1], 1)
|
| 1009 |
+
>>> encoding["bbox"] = bbox
|
| 1010 |
+
|
| 1011 |
+
>>> outputs = model(**encoding)
|
| 1012 |
+
```"""
|
| 1013 |
+
|
| 1014 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 1015 |
+
|
| 1016 |
+
outputs = self.bros(
|
| 1017 |
+
input_ids,
|
| 1018 |
+
bbox=bbox,
|
| 1019 |
+
attention_mask=attention_mask,
|
| 1020 |
+
token_type_ids=token_type_ids,
|
| 1021 |
+
position_ids=position_ids,
|
| 1022 |
+
head_mask=head_mask,
|
| 1023 |
+
inputs_embeds=inputs_embeds,
|
| 1024 |
+
output_attentions=output_attentions,
|
| 1025 |
+
output_hidden_states=output_hidden_states,
|
| 1026 |
+
return_dict=return_dict,
|
| 1027 |
+
)
|
| 1028 |
+
|
| 1029 |
+
sequence_output = outputs[0]
|
| 1030 |
+
|
| 1031 |
+
sequence_output = self.dropout(sequence_output)
|
| 1032 |
+
logits = self.classifier(sequence_output)
|
| 1033 |
+
|
| 1034 |
+
loss = None
|
| 1035 |
+
if labels is not None:
|
| 1036 |
+
loss_fct = CrossEntropyLoss()
|
| 1037 |
+
if bbox_first_token_mask is not None:
|
| 1038 |
+
bbox_first_token_mask = bbox_first_token_mask.view(-1)
|
| 1039 |
+
loss = loss_fct(
|
| 1040 |
+
logits.view(-1, self.num_labels)[bbox_first_token_mask], labels.view(-1)[bbox_first_token_mask]
|
| 1041 |
+
)
|
| 1042 |
+
else:
|
| 1043 |
+
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
|
| 1044 |
+
|
| 1045 |
+
if not return_dict:
|
| 1046 |
+
output = (logits,) + outputs[2:]
|
| 1047 |
+
return ((loss,) + output) if loss is not None else output
|
| 1048 |
+
|
| 1049 |
+
return TokenClassifierOutput(
|
| 1050 |
+
loss=loss,
|
| 1051 |
+
logits=logits,
|
| 1052 |
+
hidden_states=outputs.hidden_states,
|
| 1053 |
+
attentions=outputs.attentions,
|
| 1054 |
+
)
|
| 1055 |
+
|
| 1056 |
+
|
| 1057 |
+
@add_start_docstrings(
|
| 1058 |
+
"""
|
| 1059 |
+
Bros Model with a token classification head on top (initial_token_layers and subsequent_token_layer on top of the
|
| 1060 |
+
hidden-states output) e.g. for Named-Entity-Recognition (NER) tasks. The initial_token_classifier is used to
|
| 1061 |
+
predict the first token of each entity, and the subsequent_token_classifier is used to predict the subsequent
|
| 1062 |
+
tokens within an entity. Compared to BrosForTokenClassification, this model is more robust to serialization errors
|
| 1063 |
+
since it predicts next token from one token.
|
| 1064 |
+
""",
|
| 1065 |
+
BROS_START_DOCSTRING,
|
| 1066 |
+
)
|
| 1067 |
+
class BrosSpadeEEForTokenClassification(BrosPreTrainedModel):
|
| 1068 |
+
_keys_to_ignore_on_load_unexpected = [r"pooler"]
|
| 1069 |
+
|
| 1070 |
+
def __init__(self, config):
|
| 1071 |
+
super().__init__(config)
|
| 1072 |
+
self.config = config
|
| 1073 |
+
self.num_labels = config.num_labels
|
| 1074 |
+
self.n_relations = config.n_relations
|
| 1075 |
+
self.backbone_hidden_size = config.hidden_size
|
| 1076 |
+
|
| 1077 |
+
self.bros = BrosModel(config)
|
| 1078 |
+
classifier_dropout = (
|
| 1079 |
+
config.classifier_dropout if hasattr(config, "classifier_dropout") else config.hidden_dropout_prob
|
| 1080 |
+
)
|
| 1081 |
+
|
| 1082 |
+
# Initial token classification for Entity Extraction (NER)
|
| 1083 |
+
self.initial_token_classifier = nn.Sequential(
|
| 1084 |
+
nn.Dropout(classifier_dropout),
|
| 1085 |
+
nn.Linear(config.hidden_size, config.hidden_size),
|
| 1086 |
+
nn.Dropout(classifier_dropout),
|
| 1087 |
+
nn.Linear(config.hidden_size, config.num_labels),
|
| 1088 |
+
)
|
| 1089 |
+
|
| 1090 |
+
# Subsequent token classification for Entity Extraction (NER)
|
| 1091 |
+
self.subsequent_token_classifier = BrosRelationExtractor(config)
|
| 1092 |
+
|
| 1093 |
+
self.init_weights()
|
| 1094 |
+
|
| 1095 |
+
@add_start_docstrings_to_model_forward(BROS_INPUTS_DOCSTRING.format("batch_size, sequence_length"))
|
| 1096 |
+
@replace_return_docstrings(output_type=BrosSpadeOutput, config_class=_CONFIG_FOR_DOC)
|
| 1097 |
+
def forward(
|
| 1098 |
+
self,
|
| 1099 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 1100 |
+
bbox: Optional[torch.Tensor] = None,
|
| 1101 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 1102 |
+
bbox_first_token_mask: Optional[torch.Tensor] = None,
|
| 1103 |
+
token_type_ids: Optional[torch.Tensor] = None,
|
| 1104 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 1105 |
+
head_mask: Optional[torch.Tensor] = None,
|
| 1106 |
+
inputs_embeds: Optional[torch.Tensor] = None,
|
| 1107 |
+
initial_token_labels: Optional[torch.Tensor] = None,
|
| 1108 |
+
subsequent_token_labels: Optional[torch.Tensor] = None,
|
| 1109 |
+
output_attentions: Optional[bool] = None,
|
| 1110 |
+
output_hidden_states: Optional[bool] = None,
|
| 1111 |
+
return_dict: Optional[bool] = None,
|
| 1112 |
+
) -> Union[Tuple[torch.Tensor], BrosSpadeOutput]:
|
| 1113 |
+
r"""
|
| 1114 |
+
Returns:
|
| 1115 |
+
|
| 1116 |
+
Examples:
|
| 1117 |
+
|
| 1118 |
+
```python
|
| 1119 |
+
>>> import torch
|
| 1120 |
+
>>> from transformers import BrosProcessor, BrosSpadeEEForTokenClassification
|
| 1121 |
+
|
| 1122 |
+
>>> processor = BrosProcessor.from_pretrained("jinho8345/bros-base-uncased")
|
| 1123 |
+
|
| 1124 |
+
>>> model = BrosSpadeEEForTokenClassification.from_pretrained("jinho8345/bros-base-uncased")
|
| 1125 |
+
|
| 1126 |
+
>>> encoding = processor("Hello, my dog is cute", add_special_tokens=False, return_tensors="pt")
|
| 1127 |
+
>>> bbox = torch.tensor([[[0, 0, 1, 1]]]).repeat(1, encoding["input_ids"].shape[-1], 1)
|
| 1128 |
+
>>> encoding["bbox"] = bbox
|
| 1129 |
+
|
| 1130 |
+
>>> outputs = model(**encoding)
|
| 1131 |
+
```"""
|
| 1132 |
+
|
| 1133 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 1134 |
+
|
| 1135 |
+
outputs = self.bros(
|
| 1136 |
+
input_ids=input_ids,
|
| 1137 |
+
bbox=bbox,
|
| 1138 |
+
attention_mask=attention_mask,
|
| 1139 |
+
token_type_ids=token_type_ids,
|
| 1140 |
+
position_ids=position_ids,
|
| 1141 |
+
head_mask=head_mask,
|
| 1142 |
+
inputs_embeds=inputs_embeds,
|
| 1143 |
+
output_attentions=output_attentions,
|
| 1144 |
+
output_hidden_states=output_hidden_states,
|
| 1145 |
+
return_dict=return_dict,
|
| 1146 |
+
)
|
| 1147 |
+
|
| 1148 |
+
last_hidden_states = outputs[0]
|
| 1149 |
+
last_hidden_states = last_hidden_states.transpose(0, 1).contiguous()
|
| 1150 |
+
initial_token_logits = self.initial_token_classifier(last_hidden_states).transpose(0, 1).contiguous()
|
| 1151 |
+
subsequent_token_logits = self.subsequent_token_classifier(last_hidden_states, last_hidden_states).squeeze(0)
|
| 1152 |
+
|
| 1153 |
+
# make subsequent token (sequence token classification) mask
|
| 1154 |
+
inv_attention_mask = 1 - attention_mask
|
| 1155 |
+
batch_size, max_seq_length = inv_attention_mask.shape
|
| 1156 |
+
device = inv_attention_mask.device
|
| 1157 |
+
invalid_token_mask = torch.cat([inv_attention_mask, torch.zeros([batch_size, 1]).to(device)], axis=1).bool()
|
| 1158 |
+
subsequent_token_logits = subsequent_token_logits.masked_fill(
|
| 1159 |
+
invalid_token_mask[:, None, :], torch.finfo(subsequent_token_logits.dtype).min
|
| 1160 |
+
)
|
| 1161 |
+
self_token_mask = torch.eye(max_seq_length, max_seq_length + 1).to(device=device, dtype=torch.bool)
|
| 1162 |
+
subsequent_token_logits = subsequent_token_logits.masked_fill(
|
| 1163 |
+
self_token_mask[None, :, :], torch.finfo(subsequent_token_logits.dtype).min
|
| 1164 |
+
)
|
| 1165 |
+
subsequent_token_mask = attention_mask.view(-1).bool()
|
| 1166 |
+
|
| 1167 |
+
loss = None
|
| 1168 |
+
if initial_token_labels is not None and subsequent_token_labels is not None:
|
| 1169 |
+
loss_fct = CrossEntropyLoss()
|
| 1170 |
+
|
| 1171 |
+
# get initial token loss
|
| 1172 |
+
initial_token_labels = initial_token_labels.view(-1)
|
| 1173 |
+
if bbox_first_token_mask is not None:
|
| 1174 |
+
bbox_first_token_mask = bbox_first_token_mask.view(-1)
|
| 1175 |
+
initial_token_loss = loss_fct(
|
| 1176 |
+
initial_token_logits.view(-1, self.num_labels)[bbox_first_token_mask],
|
| 1177 |
+
initial_token_labels[bbox_first_token_mask],
|
| 1178 |
+
)
|
| 1179 |
+
else:
|
| 1180 |
+
initial_token_loss = loss_fct(initial_token_logits.view(-1, self.num_labels), initial_token_labels)
|
| 1181 |
+
|
| 1182 |
+
subsequent_token_labels = subsequent_token_labels.view(-1)
|
| 1183 |
+
subsequent_token_loss = loss_fct(
|
| 1184 |
+
subsequent_token_logits.view(-1, max_seq_length + 1)[subsequent_token_mask],
|
| 1185 |
+
subsequent_token_labels[subsequent_token_mask],
|
| 1186 |
+
)
|
| 1187 |
+
|
| 1188 |
+
loss = initial_token_loss + subsequent_token_loss
|
| 1189 |
+
|
| 1190 |
+
if not return_dict:
|
| 1191 |
+
output = (initial_token_logits, subsequent_token_logits) + outputs[2:]
|
| 1192 |
+
return ((loss,) + output) if loss is not None else output
|
| 1193 |
+
|
| 1194 |
+
return BrosSpadeOutput(
|
| 1195 |
+
loss=loss,
|
| 1196 |
+
initial_token_logits=initial_token_logits,
|
| 1197 |
+
subsequent_token_logits=subsequent_token_logits,
|
| 1198 |
+
hidden_states=outputs.hidden_states,
|
| 1199 |
+
attentions=outputs.attentions,
|
| 1200 |
+
)
|
| 1201 |
+
|
| 1202 |
+
|
| 1203 |
+
@add_start_docstrings(
|
| 1204 |
+
"""
|
| 1205 |
+
Bros Model with a token classification head on top (a entity_linker layer on top of the hidden-states output) e.g.
|
| 1206 |
+
for Entity-Linking. The entity_linker is used to predict intra-entity links (one entity to another entity).
|
| 1207 |
+
""",
|
| 1208 |
+
BROS_START_DOCSTRING,
|
| 1209 |
+
)
|
| 1210 |
+
class BrosSpadeELForTokenClassification(BrosPreTrainedModel):
|
| 1211 |
+
_keys_to_ignore_on_load_unexpected = [r"pooler"]
|
| 1212 |
+
|
| 1213 |
+
def __init__(self, config):
|
| 1214 |
+
super().__init__(config)
|
| 1215 |
+
self.config = config
|
| 1216 |
+
self.num_labels = config.num_labels
|
| 1217 |
+
self.n_relations = config.n_relations
|
| 1218 |
+
self.backbone_hidden_size = config.hidden_size
|
| 1219 |
+
|
| 1220 |
+
self.bros = BrosModel(config)
|
| 1221 |
+
(config.classifier_dropout if hasattr(config, "classifier_dropout") else config.hidden_dropout_prob)
|
| 1222 |
+
|
| 1223 |
+
self.entity_linker = BrosRelationExtractor(config)
|
| 1224 |
+
|
| 1225 |
+
self.init_weights()
|
| 1226 |
+
|
| 1227 |
+
@add_start_docstrings_to_model_forward(BROS_INPUTS_DOCSTRING.format("batch_size, sequence_length"))
|
| 1228 |
+
@replace_return_docstrings(output_type=TokenClassifierOutput, config_class=_CONFIG_FOR_DOC)
|
| 1229 |
+
def forward(
|
| 1230 |
+
self,
|
| 1231 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 1232 |
+
bbox: Optional[torch.Tensor] = None,
|
| 1233 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 1234 |
+
bbox_first_token_mask: Optional[torch.Tensor] = None,
|
| 1235 |
+
token_type_ids: Optional[torch.Tensor] = None,
|
| 1236 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 1237 |
+
head_mask: Optional[torch.Tensor] = None,
|
| 1238 |
+
inputs_embeds: Optional[torch.Tensor] = None,
|
| 1239 |
+
labels: Optional[torch.Tensor] = None,
|
| 1240 |
+
output_attentions: Optional[bool] = None,
|
| 1241 |
+
output_hidden_states: Optional[bool] = None,
|
| 1242 |
+
return_dict: Optional[bool] = None,
|
| 1243 |
+
) -> Union[Tuple[torch.Tensor], TokenClassifierOutput]:
|
| 1244 |
+
r"""
|
| 1245 |
+
Returns:
|
| 1246 |
+
|
| 1247 |
+
Examples:
|
| 1248 |
+
|
| 1249 |
+
```python
|
| 1250 |
+
>>> import torch
|
| 1251 |
+
>>> from transformers import BrosProcessor, BrosSpadeELForTokenClassification
|
| 1252 |
+
|
| 1253 |
+
>>> processor = BrosProcessor.from_pretrained("jinho8345/bros-base-uncased")
|
| 1254 |
+
|
| 1255 |
+
>>> model = BrosSpadeELForTokenClassification.from_pretrained("jinho8345/bros-base-uncased")
|
| 1256 |
+
|
| 1257 |
+
>>> encoding = processor("Hello, my dog is cute", add_special_tokens=False, return_tensors="pt")
|
| 1258 |
+
>>> bbox = torch.tensor([[[0, 0, 1, 1]]]).repeat(1, encoding["input_ids"].shape[-1], 1)
|
| 1259 |
+
>>> encoding["bbox"] = bbox
|
| 1260 |
+
|
| 1261 |
+
>>> outputs = model(**encoding)
|
| 1262 |
+
```"""
|
| 1263 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 1264 |
+
|
| 1265 |
+
outputs = self.bros(
|
| 1266 |
+
input_ids=input_ids,
|
| 1267 |
+
bbox=bbox,
|
| 1268 |
+
attention_mask=attention_mask,
|
| 1269 |
+
token_type_ids=token_type_ids,
|
| 1270 |
+
position_ids=position_ids,
|
| 1271 |
+
head_mask=head_mask,
|
| 1272 |
+
inputs_embeds=inputs_embeds,
|
| 1273 |
+
output_attentions=output_attentions,
|
| 1274 |
+
output_hidden_states=output_hidden_states,
|
| 1275 |
+
return_dict=return_dict,
|
| 1276 |
+
)
|
| 1277 |
+
|
| 1278 |
+
last_hidden_states = outputs[0]
|
| 1279 |
+
last_hidden_states = last_hidden_states.transpose(0, 1).contiguous()
|
| 1280 |
+
|
| 1281 |
+
logits = self.entity_linker(last_hidden_states, last_hidden_states).squeeze(0)
|
| 1282 |
+
|
| 1283 |
+
loss = None
|
| 1284 |
+
if labels is not None:
|
| 1285 |
+
loss_fct = CrossEntropyLoss()
|
| 1286 |
+
|
| 1287 |
+
batch_size, max_seq_length = attention_mask.shape
|
| 1288 |
+
device = attention_mask.device
|
| 1289 |
+
|
| 1290 |
+
self_token_mask = torch.eye(max_seq_length, max_seq_length + 1).to(device=device, dtype=torch.bool)
|
| 1291 |
+
|
| 1292 |
+
mask = bbox_first_token_mask.view(-1)
|
| 1293 |
+
bbox_first_token_mask = torch.cat(
|
| 1294 |
+
[
|
| 1295 |
+
~bbox_first_token_mask,
|
| 1296 |
+
torch.zeros([batch_size, 1], dtype=torch.bool, device=device),
|
| 1297 |
+
],
|
| 1298 |
+
axis=1,
|
| 1299 |
+
)
|
| 1300 |
+
logits = logits.masked_fill(bbox_first_token_mask[:, None, :], torch.finfo(logits.dtype).min)
|
| 1301 |
+
logits = logits.masked_fill(self_token_mask[None, :, :], torch.finfo(logits.dtype).min)
|
| 1302 |
+
|
| 1303 |
+
loss = loss_fct(logits.view(-1, max_seq_length + 1)[mask], labels.view(-1)[mask])
|
| 1304 |
+
|
| 1305 |
+
if not return_dict:
|
| 1306 |
+
output = (logits,) + outputs[2:]
|
| 1307 |
+
return ((loss,) + output) if loss is not None else output
|
| 1308 |
+
|
| 1309 |
+
return TokenClassifierOutput(
|
| 1310 |
+
loss=loss,
|
| 1311 |
+
logits=logits,
|
| 1312 |
+
hidden_states=outputs.hidden_states,
|
| 1313 |
+
attentions=outputs.attentions,
|
| 1314 |
+
)
|
| 1315 |
+
|
| 1316 |
+
|
| 1317 |
+
__all__ = [
|
| 1318 |
+
"BrosPreTrainedModel",
|
| 1319 |
+
"BrosModel",
|
| 1320 |
+
"BrosForTokenClassification",
|
| 1321 |
+
"BrosSpadeEEForTokenClassification",
|
| 1322 |
+
"BrosSpadeELForTokenClassification",
|
| 1323 |
+
]
|
lib/python3.12/site-packages/transformers/models/bros/processing_bros.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2023 The HuggingFace Inc. team.
|
| 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 |
+
"""
|
| 16 |
+
Processor class for Bros.
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
from typing import List, Optional, Union
|
| 20 |
+
|
| 21 |
+
from ...processing_utils import ProcessorMixin
|
| 22 |
+
from ...tokenization_utils_base import BatchEncoding, PaddingStrategy, PreTokenizedInput, TextInput, TruncationStrategy
|
| 23 |
+
from ...utils import TensorType
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class BrosProcessor(ProcessorMixin):
|
| 27 |
+
r"""
|
| 28 |
+
Constructs a Bros processor which wraps a BERT tokenizer.
|
| 29 |
+
|
| 30 |
+
[`BrosProcessor`] offers all the functionalities of [`BertTokenizerFast`]. See the docstring of
|
| 31 |
+
[`~BrosProcessor.__call__`] and [`~BrosProcessor.decode`] for more information.
|
| 32 |
+
|
| 33 |
+
Args:
|
| 34 |
+
tokenizer (`BertTokenizerFast`, *optional*):
|
| 35 |
+
An instance of ['BertTokenizerFast`]. The tokenizer is a required input.
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
attributes = ["tokenizer"]
|
| 39 |
+
tokenizer_class = ("BertTokenizer", "BertTokenizerFast")
|
| 40 |
+
|
| 41 |
+
def __init__(self, tokenizer=None, **kwargs):
|
| 42 |
+
if tokenizer is None:
|
| 43 |
+
raise ValueError("You need to specify a `tokenizer`.")
|
| 44 |
+
|
| 45 |
+
super().__init__(tokenizer)
|
| 46 |
+
|
| 47 |
+
def __call__(
|
| 48 |
+
self,
|
| 49 |
+
text: Union[TextInput, PreTokenizedInput, List[TextInput], List[PreTokenizedInput]] = None,
|
| 50 |
+
add_special_tokens: bool = True,
|
| 51 |
+
padding: Union[bool, str, PaddingStrategy] = False,
|
| 52 |
+
truncation: Union[bool, str, TruncationStrategy] = None,
|
| 53 |
+
max_length: Optional[int] = None,
|
| 54 |
+
stride: int = 0,
|
| 55 |
+
pad_to_multiple_of: Optional[int] = None,
|
| 56 |
+
return_token_type_ids: Optional[bool] = None,
|
| 57 |
+
return_attention_mask: Optional[bool] = None,
|
| 58 |
+
return_overflowing_tokens: bool = False,
|
| 59 |
+
return_special_tokens_mask: bool = False,
|
| 60 |
+
return_offsets_mapping: bool = False,
|
| 61 |
+
return_length: bool = False,
|
| 62 |
+
verbose: bool = True,
|
| 63 |
+
return_tensors: Optional[Union[str, TensorType]] = None,
|
| 64 |
+
**kwargs,
|
| 65 |
+
) -> BatchEncoding:
|
| 66 |
+
"""
|
| 67 |
+
This method uses [`BertTokenizerFast.__call__`] to prepare text for the model.
|
| 68 |
+
|
| 69 |
+
Please refer to the docstring of the above two methods for more information.
|
| 70 |
+
"""
|
| 71 |
+
encoding = self.tokenizer(
|
| 72 |
+
text=text,
|
| 73 |
+
add_special_tokens=add_special_tokens,
|
| 74 |
+
padding=padding,
|
| 75 |
+
truncation=truncation,
|
| 76 |
+
max_length=max_length,
|
| 77 |
+
stride=stride,
|
| 78 |
+
pad_to_multiple_of=pad_to_multiple_of,
|
| 79 |
+
return_token_type_ids=return_token_type_ids,
|
| 80 |
+
return_attention_mask=return_attention_mask,
|
| 81 |
+
return_overflowing_tokens=return_overflowing_tokens,
|
| 82 |
+
return_special_tokens_mask=return_special_tokens_mask,
|
| 83 |
+
return_offsets_mapping=return_offsets_mapping,
|
| 84 |
+
return_length=return_length,
|
| 85 |
+
verbose=verbose,
|
| 86 |
+
return_tensors=return_tensors,
|
| 87 |
+
**kwargs,
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
return encoding
|
| 91 |
+
|
| 92 |
+
def batch_decode(self, *args, **kwargs):
|
| 93 |
+
"""
|
| 94 |
+
This method forwards all its arguments to BertTokenizerFast's [`~PreTrainedTokenizer.batch_decode`]. Please
|
| 95 |
+
refer to the docstring of this method for more information.
|
| 96 |
+
"""
|
| 97 |
+
return self.tokenizer.batch_decode(*args, **kwargs)
|
| 98 |
+
|
| 99 |
+
def decode(self, *args, **kwargs):
|
| 100 |
+
"""
|
| 101 |
+
This method forwards all its arguments to BertTokenizerFast's [`~PreTrainedTokenizer.decode`]. Please refer to
|
| 102 |
+
the docstring of this method for more information.
|
| 103 |
+
"""
|
| 104 |
+
return self.tokenizer.decode(*args, **kwargs)
|
| 105 |
+
|
| 106 |
+
@property
|
| 107 |
+
def model_input_names(self):
|
| 108 |
+
tokenizer_input_names = self.tokenizer.model_input_names
|
| 109 |
+
return list(dict.fromkeys(tokenizer_input_names))
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
__all__ = ["BrosProcessor"]
|
lib/python3.12/site-packages/transformers/models/clip/__init__.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 .feature_extraction_clip import *
|
| 23 |
+
from .image_processing_clip import *
|
| 24 |
+
from .image_processing_clip_fast import *
|
| 25 |
+
from .modeling_clip import *
|
| 26 |
+
from .modeling_flax_clip import *
|
| 27 |
+
from .modeling_tf_clip import *
|
| 28 |
+
from .processing_clip import *
|
| 29 |
+
from .tokenization_clip import *
|
| 30 |
+
from .tokenization_clip_fast import *
|
| 31 |
+
else:
|
| 32 |
+
import sys
|
| 33 |
+
|
| 34 |
+
_file = globals()["__file__"]
|
| 35 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (939 Bytes). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/configuration_clip.cpython-312.pyc
ADDED
|
Binary file (17.5 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/feature_extraction_clip.cpython-312.pyc
ADDED
|
Binary file (1.2 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/image_processing_clip.cpython-312.pyc
ADDED
|
Binary file (15.2 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/image_processing_clip_fast.cpython-312.pyc
ADDED
|
Binary file (1.22 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/modeling_clip.cpython-312.pyc
ADDED
|
Binary file (77.5 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/modeling_flax_clip.cpython-312.pyc
ADDED
|
Binary file (58.9 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/modeling_tf_clip.cpython-312.pyc
ADDED
|
Binary file (67.1 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/processing_clip.cpython-312.pyc
ADDED
|
Binary file (7.72 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/tokenization_clip.cpython-312.pyc
ADDED
|
Binary file (24.7 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/__pycache__/tokenization_clip_fast.cpython-312.pyc
ADDED
|
Binary file (7.13 kB). View file
|
|
|
lib/python3.12/site-packages/transformers/models/clip/configuration_clip.py
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2021 The HuggingFace Inc. team. All rights reserved.
|
| 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 |
+
"""CLIP model configuration"""
|
| 16 |
+
|
| 17 |
+
from collections import OrderedDict
|
| 18 |
+
from typing import TYPE_CHECKING, Any, Mapping, Optional
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
if TYPE_CHECKING:
|
| 22 |
+
from ...processing_utils import ProcessorMixin
|
| 23 |
+
from ...utils import TensorType
|
| 24 |
+
|
| 25 |
+
from ...configuration_utils import PretrainedConfig
|
| 26 |
+
from ...onnx import OnnxConfig
|
| 27 |
+
from ...utils import logging
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
logger = logging.get_logger(__name__)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
class CLIPTextConfig(PretrainedConfig):
|
| 34 |
+
r"""
|
| 35 |
+
This is the configuration class to store the configuration of a [`CLIPTextModel`]. It is used to instantiate a CLIP
|
| 36 |
+
text encoder according to the specified arguments, defining the model architecture. Instantiating a configuration
|
| 37 |
+
with the defaults will yield a similar configuration to that of the text encoder of the CLIP
|
| 38 |
+
[openai/clip-vit-base-patch32](https://huggingface.co/openai/clip-vit-base-patch32) architecture.
|
| 39 |
+
|
| 40 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 41 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 42 |
+
|
| 43 |
+
Args:
|
| 44 |
+
vocab_size (`int`, *optional*, defaults to 49408):
|
| 45 |
+
Vocabulary size of the CLIP text model. Defines the number of different tokens that can be represented by
|
| 46 |
+
the `inputs_ids` passed when calling [`CLIPModel`].
|
| 47 |
+
hidden_size (`int`, *optional*, defaults to 512):
|
| 48 |
+
Dimensionality of the encoder layers and the pooler layer.
|
| 49 |
+
intermediate_size (`int`, *optional*, defaults to 2048):
|
| 50 |
+
Dimensionality of the "intermediate" (i.e., feed-forward) layer in the Transformer encoder.
|
| 51 |
+
projection_dim (`int`, *optional*, defaults to 512):
|
| 52 |
+
Dimensionality of text and vision projection layers.
|
| 53 |
+
num_hidden_layers (`int`, *optional*, defaults to 12):
|
| 54 |
+
Number of hidden layers in the Transformer encoder.
|
| 55 |
+
num_attention_heads (`int`, *optional*, defaults to 8):
|
| 56 |
+
Number of attention heads for each attention layer in the Transformer encoder.
|
| 57 |
+
max_position_embeddings (`int`, *optional*, defaults to 77):
|
| 58 |
+
The maximum sequence length that this model might ever be used with. Typically set this to something large
|
| 59 |
+
just in case (e.g., 512 or 1024 or 2048).
|
| 60 |
+
hidden_act (`str` or `function`, *optional*, defaults to `"quick_gelu"`):
|
| 61 |
+
The non-linear activation function (function or string) in the encoder and pooler. If string, `"gelu"`,
|
| 62 |
+
`"relu"`, `"selu"` and `"gelu_new"` `"quick_gelu"` are supported.
|
| 63 |
+
layer_norm_eps (`float`, *optional*, defaults to 1e-05):
|
| 64 |
+
The epsilon used by the layer normalization layers.
|
| 65 |
+
attention_dropout (`float`, *optional*, defaults to 0.0):
|
| 66 |
+
The dropout ratio for the attention probabilities.
|
| 67 |
+
initializer_range (`float`, *optional*, defaults to 0.02):
|
| 68 |
+
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
| 69 |
+
initializer_factor (`float`, *optional*, defaults to 1.0):
|
| 70 |
+
A factor for initializing all weight matrices (should be kept to 1, used internally for initialization
|
| 71 |
+
testing).
|
| 72 |
+
pad_token_id (`int`, *optional*, defaults to 1):
|
| 73 |
+
Padding token id.
|
| 74 |
+
bos_token_id (`int`, *optional*, defaults to 49406):
|
| 75 |
+
Beginning of stream token id.
|
| 76 |
+
eos_token_id (`int`, *optional*, defaults to 49407):
|
| 77 |
+
End of stream token id.
|
| 78 |
+
|
| 79 |
+
Example:
|
| 80 |
+
|
| 81 |
+
```python
|
| 82 |
+
>>> from transformers import CLIPTextConfig, CLIPTextModel
|
| 83 |
+
|
| 84 |
+
>>> # Initializing a CLIPTextConfig with openai/clip-vit-base-patch32 style configuration
|
| 85 |
+
>>> configuration = CLIPTextConfig()
|
| 86 |
+
|
| 87 |
+
>>> # Initializing a CLIPTextModel (with random weights) from the openai/clip-vit-base-patch32 style configuration
|
| 88 |
+
>>> model = CLIPTextModel(configuration)
|
| 89 |
+
|
| 90 |
+
>>> # Accessing the model configuration
|
| 91 |
+
>>> configuration = model.config
|
| 92 |
+
```"""
|
| 93 |
+
|
| 94 |
+
model_type = "clip_text_model"
|
| 95 |
+
base_config_key = "text_config"
|
| 96 |
+
|
| 97 |
+
def __init__(
|
| 98 |
+
self,
|
| 99 |
+
vocab_size=49408,
|
| 100 |
+
hidden_size=512,
|
| 101 |
+
intermediate_size=2048,
|
| 102 |
+
projection_dim=512,
|
| 103 |
+
num_hidden_layers=12,
|
| 104 |
+
num_attention_heads=8,
|
| 105 |
+
max_position_embeddings=77,
|
| 106 |
+
hidden_act="quick_gelu",
|
| 107 |
+
layer_norm_eps=1e-5,
|
| 108 |
+
attention_dropout=0.0,
|
| 109 |
+
initializer_range=0.02,
|
| 110 |
+
initializer_factor=1.0,
|
| 111 |
+
# This differs from `CLIPTokenizer`'s default and from openai/clip
|
| 112 |
+
# See https://github.com/huggingface/transformers/pull/24773#issuecomment-1632287538
|
| 113 |
+
pad_token_id=1,
|
| 114 |
+
bos_token_id=49406,
|
| 115 |
+
eos_token_id=49407,
|
| 116 |
+
**kwargs,
|
| 117 |
+
):
|
| 118 |
+
super().__init__(pad_token_id=pad_token_id, bos_token_id=bos_token_id, eos_token_id=eos_token_id, **kwargs)
|
| 119 |
+
|
| 120 |
+
self.vocab_size = vocab_size
|
| 121 |
+
self.hidden_size = hidden_size
|
| 122 |
+
self.intermediate_size = intermediate_size
|
| 123 |
+
self.projection_dim = projection_dim
|
| 124 |
+
self.num_hidden_layers = num_hidden_layers
|
| 125 |
+
self.num_attention_heads = num_attention_heads
|
| 126 |
+
self.max_position_embeddings = max_position_embeddings
|
| 127 |
+
self.layer_norm_eps = layer_norm_eps
|
| 128 |
+
self.hidden_act = hidden_act
|
| 129 |
+
self.initializer_range = initializer_range
|
| 130 |
+
self.initializer_factor = initializer_factor
|
| 131 |
+
self.attention_dropout = attention_dropout
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
class CLIPVisionConfig(PretrainedConfig):
|
| 135 |
+
r"""
|
| 136 |
+
This is the configuration class to store the configuration of a [`CLIPVisionModel`]. It is used to instantiate a
|
| 137 |
+
CLIP vision encoder according to the specified arguments, defining the model architecture. Instantiating a
|
| 138 |
+
configuration with the defaults will yield a similar configuration to that of the vision encoder of the CLIP
|
| 139 |
+
[openai/clip-vit-base-patch32](https://huggingface.co/openai/clip-vit-base-patch32) architecture.
|
| 140 |
+
|
| 141 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 142 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 143 |
+
|
| 144 |
+
Args:
|
| 145 |
+
hidden_size (`int`, *optional*, defaults to 768):
|
| 146 |
+
Dimensionality of the encoder layers and the pooler layer.
|
| 147 |
+
intermediate_size (`int`, *optional*, defaults to 3072):
|
| 148 |
+
Dimensionality of the "intermediate" (i.e., feed-forward) layer in the Transformer encoder.
|
| 149 |
+
projection_dim (`int`, *optional*, defaults to 512):
|
| 150 |
+
Dimensionality of text and vision projection layers.
|
| 151 |
+
num_hidden_layers (`int`, *optional*, defaults to 12):
|
| 152 |
+
Number of hidden layers in the Transformer encoder.
|
| 153 |
+
num_attention_heads (`int`, *optional*, defaults to 12):
|
| 154 |
+
Number of attention heads for each attention layer in the Transformer encoder.
|
| 155 |
+
num_channels (`int`, *optional*, defaults to 3):
|
| 156 |
+
The number of input channels.
|
| 157 |
+
image_size (`int`, *optional*, defaults to 224):
|
| 158 |
+
The size (resolution) of each image.
|
| 159 |
+
patch_size (`int`, *optional*, defaults to 32):
|
| 160 |
+
The size (resolution) of each patch.
|
| 161 |
+
hidden_act (`str` or `function`, *optional*, defaults to `"quick_gelu"`):
|
| 162 |
+
The non-linear activation function (function or string) in the encoder and pooler. If string, `"gelu"`,
|
| 163 |
+
`"relu"`, `"selu"` and `"gelu_new"` `"quick_gelu"` are supported.
|
| 164 |
+
layer_norm_eps (`float`, *optional*, defaults to 1e-05):
|
| 165 |
+
The epsilon used by the layer normalization layers.
|
| 166 |
+
attention_dropout (`float`, *optional*, defaults to 0.0):
|
| 167 |
+
The dropout ratio for the attention probabilities.
|
| 168 |
+
initializer_range (`float`, *optional*, defaults to 0.02):
|
| 169 |
+
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
| 170 |
+
initializer_factor (`float`, *optional*, defaults to 1.0):
|
| 171 |
+
A factor for initializing all weight matrices (should be kept to 1, used internally for initialization
|
| 172 |
+
testing).
|
| 173 |
+
|
| 174 |
+
Example:
|
| 175 |
+
|
| 176 |
+
```python
|
| 177 |
+
>>> from transformers import CLIPVisionConfig, CLIPVisionModel
|
| 178 |
+
|
| 179 |
+
>>> # Initializing a CLIPVisionConfig with openai/clip-vit-base-patch32 style configuration
|
| 180 |
+
>>> configuration = CLIPVisionConfig()
|
| 181 |
+
|
| 182 |
+
>>> # Initializing a CLIPVisionModel (with random weights) from the openai/clip-vit-base-patch32 style configuration
|
| 183 |
+
>>> model = CLIPVisionModel(configuration)
|
| 184 |
+
|
| 185 |
+
>>> # Accessing the model configuration
|
| 186 |
+
>>> configuration = model.config
|
| 187 |
+
```"""
|
| 188 |
+
|
| 189 |
+
model_type = "clip_vision_model"
|
| 190 |
+
base_config_key = "vision_config"
|
| 191 |
+
|
| 192 |
+
def __init__(
|
| 193 |
+
self,
|
| 194 |
+
hidden_size=768,
|
| 195 |
+
intermediate_size=3072,
|
| 196 |
+
projection_dim=512,
|
| 197 |
+
num_hidden_layers=12,
|
| 198 |
+
num_attention_heads=12,
|
| 199 |
+
num_channels=3,
|
| 200 |
+
image_size=224,
|
| 201 |
+
patch_size=32,
|
| 202 |
+
hidden_act="quick_gelu",
|
| 203 |
+
layer_norm_eps=1e-5,
|
| 204 |
+
attention_dropout=0.0,
|
| 205 |
+
initializer_range=0.02,
|
| 206 |
+
initializer_factor=1.0,
|
| 207 |
+
**kwargs,
|
| 208 |
+
):
|
| 209 |
+
super().__init__(**kwargs)
|
| 210 |
+
|
| 211 |
+
self.hidden_size = hidden_size
|
| 212 |
+
self.intermediate_size = intermediate_size
|
| 213 |
+
self.projection_dim = projection_dim
|
| 214 |
+
self.num_hidden_layers = num_hidden_layers
|
| 215 |
+
self.num_attention_heads = num_attention_heads
|
| 216 |
+
self.num_channels = num_channels
|
| 217 |
+
self.patch_size = patch_size
|
| 218 |
+
self.image_size = image_size
|
| 219 |
+
self.initializer_range = initializer_range
|
| 220 |
+
self.initializer_factor = initializer_factor
|
| 221 |
+
self.attention_dropout = attention_dropout
|
| 222 |
+
self.layer_norm_eps = layer_norm_eps
|
| 223 |
+
self.hidden_act = hidden_act
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
class CLIPConfig(PretrainedConfig):
|
| 227 |
+
r"""
|
| 228 |
+
[`CLIPConfig`] is the configuration class to store the configuration of a [`CLIPModel`]. It is used to instantiate
|
| 229 |
+
a CLIP model according to the specified arguments, defining the text model and vision model configs. Instantiating
|
| 230 |
+
a configuration with the defaults will yield a similar configuration to that of the CLIP
|
| 231 |
+
[openai/clip-vit-base-patch32](https://huggingface.co/openai/clip-vit-base-patch32) architecture.
|
| 232 |
+
|
| 233 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 234 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 235 |
+
|
| 236 |
+
Args:
|
| 237 |
+
text_config (`dict`, *optional*):
|
| 238 |
+
Dictionary of configuration options used to initialize [`CLIPTextConfig`].
|
| 239 |
+
vision_config (`dict`, *optional*):
|
| 240 |
+
Dictionary of configuration options used to initialize [`CLIPVisionConfig`].
|
| 241 |
+
projection_dim (`int`, *optional*, defaults to 512):
|
| 242 |
+
Dimensionality of text and vision projection layers.
|
| 243 |
+
logit_scale_init_value (`float`, *optional*, defaults to 2.6592):
|
| 244 |
+
The initial value of the *logit_scale* parameter. Default is used as per the original CLIP implementation.
|
| 245 |
+
kwargs (*optional*):
|
| 246 |
+
Dictionary of keyword arguments.
|
| 247 |
+
|
| 248 |
+
Example:
|
| 249 |
+
|
| 250 |
+
```python
|
| 251 |
+
>>> from transformers import CLIPConfig, CLIPModel
|
| 252 |
+
|
| 253 |
+
>>> # Initializing a CLIPConfig with openai/clip-vit-base-patch32 style configuration
|
| 254 |
+
>>> configuration = CLIPConfig()
|
| 255 |
+
|
| 256 |
+
>>> # Initializing a CLIPModel (with random weights) from the openai/clip-vit-base-patch32 style configuration
|
| 257 |
+
>>> model = CLIPModel(configuration)
|
| 258 |
+
|
| 259 |
+
>>> # Accessing the model configuration
|
| 260 |
+
>>> configuration = model.config
|
| 261 |
+
|
| 262 |
+
>>> # We can also initialize a CLIPConfig from a CLIPTextConfig and a CLIPVisionConfig
|
| 263 |
+
>>> from transformers import CLIPTextConfig, CLIPVisionConfig
|
| 264 |
+
|
| 265 |
+
>>> # Initializing a CLIPText and CLIPVision configuration
|
| 266 |
+
>>> config_text = CLIPTextConfig()
|
| 267 |
+
>>> config_vision = CLIPVisionConfig()
|
| 268 |
+
|
| 269 |
+
>>> config = CLIPConfig.from_text_vision_configs(config_text, config_vision)
|
| 270 |
+
```"""
|
| 271 |
+
|
| 272 |
+
model_type = "clip"
|
| 273 |
+
sub_configs = {"text_config": CLIPTextConfig, "vision_config": CLIPVisionConfig}
|
| 274 |
+
|
| 275 |
+
def __init__(
|
| 276 |
+
self, text_config=None, vision_config=None, projection_dim=512, logit_scale_init_value=2.6592, **kwargs
|
| 277 |
+
):
|
| 278 |
+
# If `_config_dict` exist, we use them for the backward compatibility.
|
| 279 |
+
# We pop out these 2 attributes before calling `super().__init__` to avoid them being saved (which causes a lot
|
| 280 |
+
# of confusion!).
|
| 281 |
+
text_config_dict = kwargs.pop("text_config_dict", None)
|
| 282 |
+
vision_config_dict = kwargs.pop("vision_config_dict", None)
|
| 283 |
+
|
| 284 |
+
super().__init__(**kwargs)
|
| 285 |
+
|
| 286 |
+
# Instead of simply assigning `[text|vision]_config_dict` to `[text|vision]_config`, we use the values in
|
| 287 |
+
# `[text|vision]_config_dict` to update the values in `[text|vision]_config`. The values should be same in most
|
| 288 |
+
# cases, but we don't want to break anything regarding `_config_dict` that existed before commit `8827e1b2`.
|
| 289 |
+
if text_config_dict is not None:
|
| 290 |
+
if text_config is None:
|
| 291 |
+
text_config = {}
|
| 292 |
+
|
| 293 |
+
# This is the complete result when using `text_config_dict`.
|
| 294 |
+
_text_config_dict = CLIPTextConfig(**text_config_dict).to_dict()
|
| 295 |
+
|
| 296 |
+
# Give a warning if the values exist in both `_text_config_dict` and `text_config` but being different.
|
| 297 |
+
for key, value in _text_config_dict.items():
|
| 298 |
+
if key in text_config and value != text_config[key] and key not in ["transformers_version"]:
|
| 299 |
+
# If specified in `text_config_dict`
|
| 300 |
+
if key in text_config_dict:
|
| 301 |
+
message = (
|
| 302 |
+
f"`{key}` is found in both `text_config_dict` and `text_config` but with different values. "
|
| 303 |
+
f'The value `text_config_dict["{key}"]` will be used instead.'
|
| 304 |
+
)
|
| 305 |
+
# If inferred from default argument values (just to be super careful)
|
| 306 |
+
else:
|
| 307 |
+
message = (
|
| 308 |
+
f"`text_config_dict` is provided which will be used to initialize `CLIPTextConfig`. The "
|
| 309 |
+
f'value `text_config["{key}"]` will be overridden.'
|
| 310 |
+
)
|
| 311 |
+
logger.info(message)
|
| 312 |
+
|
| 313 |
+
# Update all values in `text_config` with the ones in `_text_config_dict`.
|
| 314 |
+
text_config.update(_text_config_dict)
|
| 315 |
+
|
| 316 |
+
if vision_config_dict is not None:
|
| 317 |
+
if vision_config is None:
|
| 318 |
+
vision_config = {}
|
| 319 |
+
|
| 320 |
+
# This is the complete result when using `vision_config_dict`.
|
| 321 |
+
_vision_config_dict = CLIPVisionConfig(**vision_config_dict).to_dict()
|
| 322 |
+
# convert keys to string instead of integer
|
| 323 |
+
if "id2label" in _vision_config_dict:
|
| 324 |
+
_vision_config_dict["id2label"] = {
|
| 325 |
+
str(key): value for key, value in _vision_config_dict["id2label"].items()
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
# Give a warning if the values exist in both `_vision_config_dict` and `vision_config` but being different.
|
| 329 |
+
for key, value in _vision_config_dict.items():
|
| 330 |
+
if key in vision_config and value != vision_config[key] and key not in ["transformers_version"]:
|
| 331 |
+
# If specified in `vision_config_dict`
|
| 332 |
+
if key in vision_config_dict:
|
| 333 |
+
message = (
|
| 334 |
+
f"`{key}` is found in both `vision_config_dict` and `vision_config` but with different "
|
| 335 |
+
f'values. The value `vision_config_dict["{key}"]` will be used instead.'
|
| 336 |
+
)
|
| 337 |
+
# If inferred from default argument values (just to be super careful)
|
| 338 |
+
else:
|
| 339 |
+
message = (
|
| 340 |
+
f"`vision_config_dict` is provided which will be used to initialize `CLIPVisionConfig`. "
|
| 341 |
+
f'The value `vision_config["{key}"]` will be overridden.'
|
| 342 |
+
)
|
| 343 |
+
logger.info(message)
|
| 344 |
+
|
| 345 |
+
# Update all values in `vision_config` with the ones in `_vision_config_dict`.
|
| 346 |
+
vision_config.update(_vision_config_dict)
|
| 347 |
+
|
| 348 |
+
if text_config is None:
|
| 349 |
+
text_config = {}
|
| 350 |
+
logger.info("`text_config` is `None`. Initializing the `CLIPTextConfig` with default values.")
|
| 351 |
+
|
| 352 |
+
if vision_config is None:
|
| 353 |
+
vision_config = {}
|
| 354 |
+
logger.info("`vision_config` is `None`. initializing the `CLIPVisionConfig` with default values.")
|
| 355 |
+
|
| 356 |
+
self.text_config = CLIPTextConfig(**text_config)
|
| 357 |
+
self.vision_config = CLIPVisionConfig(**vision_config)
|
| 358 |
+
|
| 359 |
+
self.projection_dim = projection_dim
|
| 360 |
+
self.logit_scale_init_value = logit_scale_init_value
|
| 361 |
+
self.initializer_factor = 1.0
|
| 362 |
+
|
| 363 |
+
@classmethod
|
| 364 |
+
def from_text_vision_configs(cls, text_config: CLIPTextConfig, vision_config: CLIPVisionConfig, **kwargs):
|
| 365 |
+
r"""
|
| 366 |
+
Instantiate a [`CLIPConfig`] (or a derived class) from clip text model configuration and clip vision model
|
| 367 |
+
configuration.
|
| 368 |
+
|
| 369 |
+
Returns:
|
| 370 |
+
[`CLIPConfig`]: An instance of a configuration object
|
| 371 |
+
"""
|
| 372 |
+
|
| 373 |
+
return cls(text_config=text_config.to_dict(), vision_config=vision_config.to_dict(), **kwargs)
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
class CLIPOnnxConfig(OnnxConfig):
|
| 377 |
+
@property
|
| 378 |
+
def inputs(self) -> Mapping[str, Mapping[int, str]]:
|
| 379 |
+
return OrderedDict(
|
| 380 |
+
[
|
| 381 |
+
("input_ids", {0: "batch", 1: "sequence"}),
|
| 382 |
+
("pixel_values", {0: "batch", 1: "num_channels", 2: "height", 3: "width"}),
|
| 383 |
+
("attention_mask", {0: "batch", 1: "sequence"}),
|
| 384 |
+
]
|
| 385 |
+
)
|
| 386 |
+
|
| 387 |
+
@property
|
| 388 |
+
def outputs(self) -> Mapping[str, Mapping[int, str]]:
|
| 389 |
+
return OrderedDict(
|
| 390 |
+
[
|
| 391 |
+
("logits_per_image", {0: "batch"}),
|
| 392 |
+
("logits_per_text", {0: "batch"}),
|
| 393 |
+
("text_embeds", {0: "batch"}),
|
| 394 |
+
("image_embeds", {0: "batch"}),
|
| 395 |
+
]
|
| 396 |
+
)
|
| 397 |
+
|
| 398 |
+
@property
|
| 399 |
+
def atol_for_validation(self) -> float:
|
| 400 |
+
return 1e-4
|
| 401 |
+
|
| 402 |
+
def generate_dummy_inputs(
|
| 403 |
+
self,
|
| 404 |
+
processor: "ProcessorMixin",
|
| 405 |
+
batch_size: int = -1,
|
| 406 |
+
seq_length: int = -1,
|
| 407 |
+
framework: Optional["TensorType"] = None,
|
| 408 |
+
) -> Mapping[str, Any]:
|
| 409 |
+
text_input_dict = super().generate_dummy_inputs(
|
| 410 |
+
processor.tokenizer, batch_size=batch_size, seq_length=seq_length, framework=framework
|
| 411 |
+
)
|
| 412 |
+
image_input_dict = super().generate_dummy_inputs(
|
| 413 |
+
processor.image_processor, batch_size=batch_size, framework=framework
|
| 414 |
+
)
|
| 415 |
+
return {**text_input_dict, **image_input_dict}
|
| 416 |
+
|
| 417 |
+
@property
|
| 418 |
+
def default_onnx_opset(self) -> int:
|
| 419 |
+
return 14
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
__all__ = ["CLIPConfig", "CLIPOnnxConfig", "CLIPTextConfig", "CLIPVisionConfig"]
|
lib/python3.12/site-packages/transformers/models/clip/feature_extraction_clip.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2021 The HuggingFace Inc. team. All rights reserved.
|
| 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 |
+
"""Feature extractor class for CLIP."""
|
| 16 |
+
|
| 17 |
+
import warnings
|
| 18 |
+
|
| 19 |
+
from ...utils import logging
|
| 20 |
+
from .image_processing_clip import CLIPImageProcessor
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
logger = logging.get_logger(__name__)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class CLIPFeatureExtractor(CLIPImageProcessor):
|
| 27 |
+
def __init__(self, *args, **kwargs) -> None:
|
| 28 |
+
warnings.warn(
|
| 29 |
+
"The class CLIPFeatureExtractor is deprecated and will be removed in version 5 of Transformers. Please"
|
| 30 |
+
" use CLIPImageProcessor instead.",
|
| 31 |
+
FutureWarning,
|
| 32 |
+
)
|
| 33 |
+
super().__init__(*args, **kwargs)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
__all__ = ["CLIPFeatureExtractor"]
|
lib/python3.12/site-packages/transformers/models/clip/image_processing_clip.py
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2022 The HuggingFace Inc. team. All rights reserved.
|
| 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 |
+
"""Image processor class for CLIP."""
|
| 16 |
+
|
| 17 |
+
from typing import Dict, List, Optional, Union
|
| 18 |
+
|
| 19 |
+
import numpy as np
|
| 20 |
+
|
| 21 |
+
from ...image_processing_utils import BaseImageProcessor, BatchFeature, get_size_dict
|
| 22 |
+
from ...image_transforms import (
|
| 23 |
+
convert_to_rgb,
|
| 24 |
+
get_resize_output_image_size,
|
| 25 |
+
resize,
|
| 26 |
+
to_channel_dimension_format,
|
| 27 |
+
)
|
| 28 |
+
from ...image_utils import (
|
| 29 |
+
OPENAI_CLIP_MEAN,
|
| 30 |
+
OPENAI_CLIP_STD,
|
| 31 |
+
ChannelDimension,
|
| 32 |
+
ImageInput,
|
| 33 |
+
PILImageResampling,
|
| 34 |
+
infer_channel_dimension_format,
|
| 35 |
+
is_scaled_image,
|
| 36 |
+
make_flat_list_of_images,
|
| 37 |
+
to_numpy_array,
|
| 38 |
+
valid_images,
|
| 39 |
+
validate_kwargs,
|
| 40 |
+
validate_preprocess_arguments,
|
| 41 |
+
)
|
| 42 |
+
from ...utils import TensorType, is_vision_available, logging
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
logger = logging.get_logger(__name__)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
if is_vision_available():
|
| 49 |
+
import PIL
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
class CLIPImageProcessor(BaseImageProcessor):
|
| 53 |
+
r"""
|
| 54 |
+
Constructs a CLIP image processor.
|
| 55 |
+
|
| 56 |
+
Args:
|
| 57 |
+
do_resize (`bool`, *optional*, defaults to `True`):
|
| 58 |
+
Whether to resize the image's (height, width) dimensions to the specified `size`. Can be overridden by
|
| 59 |
+
`do_resize` in the `preprocess` method.
|
| 60 |
+
size (`Dict[str, int]` *optional*, defaults to `{"shortest_edge": 224}`):
|
| 61 |
+
Size of the image after resizing. The shortest edge of the image is resized to size["shortest_edge"], with
|
| 62 |
+
the longest edge resized to keep the input aspect ratio. Can be overridden by `size` in the `preprocess`
|
| 63 |
+
method.
|
| 64 |
+
resample (`PILImageResampling`, *optional*, defaults to `Resampling.BICUBIC`):
|
| 65 |
+
Resampling filter to use if resizing the image. Can be overridden by `resample` in the `preprocess` method.
|
| 66 |
+
do_center_crop (`bool`, *optional*, defaults to `True`):
|
| 67 |
+
Whether to center crop the image to the specified `crop_size`. Can be overridden by `do_center_crop` in the
|
| 68 |
+
`preprocess` method.
|
| 69 |
+
crop_size (`Dict[str, int]` *optional*, defaults to 224):
|
| 70 |
+
Size of the output image after applying `center_crop`. Can be overridden by `crop_size` in the `preprocess`
|
| 71 |
+
method.
|
| 72 |
+
do_rescale (`bool`, *optional*, defaults to `True`):
|
| 73 |
+
Whether to rescale the image by the specified scale `rescale_factor`. Can be overridden by `do_rescale` in
|
| 74 |
+
the `preprocess` method.
|
| 75 |
+
rescale_factor (`int` or `float`, *optional*, defaults to `1/255`):
|
| 76 |
+
Scale factor to use if rescaling the image. Can be overridden by `rescale_factor` in the `preprocess`
|
| 77 |
+
method.
|
| 78 |
+
do_normalize (`bool`, *optional*, defaults to `True`):
|
| 79 |
+
Whether to normalize the image. Can be overridden by `do_normalize` in the `preprocess` method.
|
| 80 |
+
image_mean (`float` or `List[float]`, *optional*, defaults to `[0.48145466, 0.4578275, 0.40821073]`):
|
| 81 |
+
Mean to use if normalizing the image. This is a float or list of floats the length of the number of
|
| 82 |
+
channels in the image. Can be overridden by the `image_mean` parameter in the `preprocess` method.
|
| 83 |
+
image_std (`float` or `List[float]`, *optional*, defaults to `[0.26862954, 0.26130258, 0.27577711]`):
|
| 84 |
+
Standard deviation to use if normalizing the image. This is a float or list of floats the length of the
|
| 85 |
+
number of channels in the image. Can be overridden by the `image_std` parameter in the `preprocess` method.
|
| 86 |
+
Can be overridden by the `image_std` parameter in the `preprocess` method.
|
| 87 |
+
do_convert_rgb (`bool`, *optional*, defaults to `True`):
|
| 88 |
+
Whether to convert the image to RGB.
|
| 89 |
+
"""
|
| 90 |
+
|
| 91 |
+
model_input_names = ["pixel_values"]
|
| 92 |
+
|
| 93 |
+
def __init__(
|
| 94 |
+
self,
|
| 95 |
+
do_resize: bool = True,
|
| 96 |
+
size: Dict[str, int] = None,
|
| 97 |
+
resample: PILImageResampling = PILImageResampling.BICUBIC,
|
| 98 |
+
do_center_crop: bool = True,
|
| 99 |
+
crop_size: Dict[str, int] = None,
|
| 100 |
+
do_rescale: bool = True,
|
| 101 |
+
rescale_factor: Union[int, float] = 1 / 255,
|
| 102 |
+
do_normalize: bool = True,
|
| 103 |
+
image_mean: Optional[Union[float, List[float]]] = None,
|
| 104 |
+
image_std: Optional[Union[float, List[float]]] = None,
|
| 105 |
+
do_convert_rgb: bool = True,
|
| 106 |
+
**kwargs,
|
| 107 |
+
) -> None:
|
| 108 |
+
super().__init__(**kwargs)
|
| 109 |
+
size = size if size is not None else {"shortest_edge": 224}
|
| 110 |
+
size = get_size_dict(size, default_to_square=False)
|
| 111 |
+
crop_size = crop_size if crop_size is not None else {"height": 224, "width": 224}
|
| 112 |
+
crop_size = get_size_dict(crop_size, default_to_square=True, param_name="crop_size")
|
| 113 |
+
|
| 114 |
+
self.do_resize = do_resize
|
| 115 |
+
self.size = size
|
| 116 |
+
self.resample = resample
|
| 117 |
+
self.do_center_crop = do_center_crop
|
| 118 |
+
self.crop_size = crop_size
|
| 119 |
+
self.do_rescale = do_rescale
|
| 120 |
+
self.rescale_factor = rescale_factor
|
| 121 |
+
self.do_normalize = do_normalize
|
| 122 |
+
self.image_mean = image_mean if image_mean is not None else OPENAI_CLIP_MEAN
|
| 123 |
+
self.image_std = image_std if image_std is not None else OPENAI_CLIP_STD
|
| 124 |
+
self.do_convert_rgb = do_convert_rgb
|
| 125 |
+
self._valid_processor_keys = [
|
| 126 |
+
"images",
|
| 127 |
+
"do_resize",
|
| 128 |
+
"size",
|
| 129 |
+
"resample",
|
| 130 |
+
"do_center_crop",
|
| 131 |
+
"crop_size",
|
| 132 |
+
"do_rescale",
|
| 133 |
+
"rescale_factor",
|
| 134 |
+
"do_normalize",
|
| 135 |
+
"image_mean",
|
| 136 |
+
"image_std",
|
| 137 |
+
"do_convert_rgb",
|
| 138 |
+
"return_tensors",
|
| 139 |
+
"data_format",
|
| 140 |
+
"input_data_format",
|
| 141 |
+
]
|
| 142 |
+
|
| 143 |
+
# for backwards compatibility of KOSMOS-2
|
| 144 |
+
if "use_square_size" in kwargs and kwargs["use_square_size"]:
|
| 145 |
+
self.size = {"height": size["shortest_edge"], "width": size["shortest_edge"]}
|
| 146 |
+
# Let's remove `use_square_size` (as it is removed from #27690), so the future Kosmos-2 image processors
|
| 147 |
+
# won't have this attr. being saved. (otherwise, it will enter this if branch while there is no more
|
| 148 |
+
# `shortest_edge` key.
|
| 149 |
+
delattr(self, "use_square_size")
|
| 150 |
+
|
| 151 |
+
def resize(
|
| 152 |
+
self,
|
| 153 |
+
image: np.ndarray,
|
| 154 |
+
size: Dict[str, int],
|
| 155 |
+
resample: PILImageResampling = PILImageResampling.BICUBIC,
|
| 156 |
+
data_format: Optional[Union[str, ChannelDimension]] = None,
|
| 157 |
+
input_data_format: Optional[Union[str, ChannelDimension]] = None,
|
| 158 |
+
**kwargs,
|
| 159 |
+
) -> np.ndarray:
|
| 160 |
+
"""
|
| 161 |
+
Resize an image. The shortest edge of the image is resized to size["shortest_edge"], with the longest edge
|
| 162 |
+
resized to keep the input aspect ratio.
|
| 163 |
+
|
| 164 |
+
Args:
|
| 165 |
+
image (`np.ndarray`):
|
| 166 |
+
Image to resize.
|
| 167 |
+
size (`Dict[str, int]`):
|
| 168 |
+
Size of the output image.
|
| 169 |
+
resample (`PILImageResampling`, *optional*, defaults to `PILImageResampling.BICUBIC`):
|
| 170 |
+
Resampling filter to use when resiizing the image.
|
| 171 |
+
data_format (`str` or `ChannelDimension`, *optional*):
|
| 172 |
+
The channel dimension format of the image. If not provided, it will be the same as the input image.
|
| 173 |
+
input_data_format (`ChannelDimension` or `str`, *optional*):
|
| 174 |
+
The channel dimension format of the input image. If not provided, it will be inferred.
|
| 175 |
+
"""
|
| 176 |
+
default_to_square = True
|
| 177 |
+
if "shortest_edge" in size:
|
| 178 |
+
size = size["shortest_edge"]
|
| 179 |
+
default_to_square = False
|
| 180 |
+
elif "height" in size and "width" in size:
|
| 181 |
+
size = (size["height"], size["width"])
|
| 182 |
+
else:
|
| 183 |
+
raise ValueError("Size must contain either 'shortest_edge' or 'height' and 'width'.")
|
| 184 |
+
|
| 185 |
+
output_size = get_resize_output_image_size(
|
| 186 |
+
image,
|
| 187 |
+
size=size,
|
| 188 |
+
default_to_square=default_to_square,
|
| 189 |
+
input_data_format=input_data_format,
|
| 190 |
+
)
|
| 191 |
+
return resize(
|
| 192 |
+
image,
|
| 193 |
+
size=output_size,
|
| 194 |
+
resample=resample,
|
| 195 |
+
data_format=data_format,
|
| 196 |
+
input_data_format=input_data_format,
|
| 197 |
+
**kwargs,
|
| 198 |
+
)
|
| 199 |
+
|
| 200 |
+
def preprocess(
|
| 201 |
+
self,
|
| 202 |
+
images: ImageInput,
|
| 203 |
+
do_resize: Optional[bool] = None,
|
| 204 |
+
size: Dict[str, int] = None,
|
| 205 |
+
resample: PILImageResampling = None,
|
| 206 |
+
do_center_crop: Optional[bool] = None,
|
| 207 |
+
crop_size: Optional[int] = None,
|
| 208 |
+
do_rescale: Optional[bool] = None,
|
| 209 |
+
rescale_factor: Optional[float] = None,
|
| 210 |
+
do_normalize: Optional[bool] = None,
|
| 211 |
+
image_mean: Optional[Union[float, List[float]]] = None,
|
| 212 |
+
image_std: Optional[Union[float, List[float]]] = None,
|
| 213 |
+
do_convert_rgb: Optional[bool] = None,
|
| 214 |
+
return_tensors: Optional[Union[str, TensorType]] = None,
|
| 215 |
+
data_format: Optional[ChannelDimension] = ChannelDimension.FIRST,
|
| 216 |
+
input_data_format: Optional[Union[str, ChannelDimension]] = None,
|
| 217 |
+
**kwargs,
|
| 218 |
+
) -> PIL.Image.Image:
|
| 219 |
+
"""
|
| 220 |
+
Preprocess an image or batch of images.
|
| 221 |
+
|
| 222 |
+
Args:
|
| 223 |
+
images (`ImageInput`):
|
| 224 |
+
Image to preprocess. Expects a single or batch of images with pixel values ranging from 0 to 255. If
|
| 225 |
+
passing in images with pixel values between 0 and 1, set `do_rescale=False`.
|
| 226 |
+
do_resize (`bool`, *optional*, defaults to `self.do_resize`):
|
| 227 |
+
Whether to resize the image.
|
| 228 |
+
size (`Dict[str, int]`, *optional*, defaults to `self.size`):
|
| 229 |
+
Size of the image after resizing. Shortest edge of the image is resized to size["shortest_edge"], with
|
| 230 |
+
the longest edge resized to keep the input aspect ratio.
|
| 231 |
+
resample (`int`, *optional*, defaults to `self.resample`):
|
| 232 |
+
Resampling filter to use if resizing the image. This can be one of the enum `PILImageResampling`. Only
|
| 233 |
+
has an effect if `do_resize` is set to `True`.
|
| 234 |
+
do_center_crop (`bool`, *optional*, defaults to `self.do_center_crop`):
|
| 235 |
+
Whether to center crop the image.
|
| 236 |
+
crop_size (`Dict[str, int]`, *optional*, defaults to `self.crop_size`):
|
| 237 |
+
Size of the center crop. Only has an effect if `do_center_crop` is set to `True`.
|
| 238 |
+
do_rescale (`bool`, *optional*, defaults to `self.do_rescale`):
|
| 239 |
+
Whether to rescale the image.
|
| 240 |
+
rescale_factor (`float`, *optional*, defaults to `self.rescale_factor`):
|
| 241 |
+
Rescale factor to rescale the image by if `do_rescale` is set to `True`.
|
| 242 |
+
do_normalize (`bool`, *optional*, defaults to `self.do_normalize`):
|
| 243 |
+
Whether to normalize the image.
|
| 244 |
+
image_mean (`float` or `List[float]`, *optional*, defaults to `self.image_mean`):
|
| 245 |
+
Image mean to use for normalization. Only has an effect if `do_normalize` is set to `True`.
|
| 246 |
+
image_std (`float` or `List[float]`, *optional*, defaults to `self.image_std`):
|
| 247 |
+
Image standard deviation to use for normalization. Only has an effect if `do_normalize` is set to
|
| 248 |
+
`True`.
|
| 249 |
+
do_convert_rgb (`bool`, *optional*, defaults to `self.do_convert_rgb`):
|
| 250 |
+
Whether to convert the image to RGB.
|
| 251 |
+
return_tensors (`str` or `TensorType`, *optional*):
|
| 252 |
+
The type of tensors to return. Can be one of:
|
| 253 |
+
- Unset: Return a list of `np.ndarray`.
|
| 254 |
+
- `TensorType.TENSORFLOW` or `'tf'`: Return a batch of type `tf.Tensor`.
|
| 255 |
+
- `TensorType.PYTORCH` or `'pt'`: Return a batch of type `torch.Tensor`.
|
| 256 |
+
- `TensorType.NUMPY` or `'np'`: Return a batch of type `np.ndarray`.
|
| 257 |
+
- `TensorType.JAX` or `'jax'`: Return a batch of type `jax.numpy.ndarray`.
|
| 258 |
+
data_format (`ChannelDimension` or `str`, *optional*, defaults to `ChannelDimension.FIRST`):
|
| 259 |
+
The channel dimension format for the output image. Can be one of:
|
| 260 |
+
- `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
|
| 261 |
+
- `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
|
| 262 |
+
- Unset: Use the channel dimension format of the input image.
|
| 263 |
+
input_data_format (`ChannelDimension` or `str`, *optional*):
|
| 264 |
+
The channel dimension format for the input image. If unset, the channel dimension format is inferred
|
| 265 |
+
from the input image. Can be one of:
|
| 266 |
+
- `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
|
| 267 |
+
- `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
|
| 268 |
+
- `"none"` or `ChannelDimension.NONE`: image in (height, width) format.
|
| 269 |
+
"""
|
| 270 |
+
do_resize = do_resize if do_resize is not None else self.do_resize
|
| 271 |
+
size = size if size is not None else self.size
|
| 272 |
+
size = get_size_dict(size, param_name="size", default_to_square=False)
|
| 273 |
+
resample = resample if resample is not None else self.resample
|
| 274 |
+
do_center_crop = do_center_crop if do_center_crop is not None else self.do_center_crop
|
| 275 |
+
crop_size = crop_size if crop_size is not None else self.crop_size
|
| 276 |
+
crop_size = get_size_dict(crop_size, param_name="crop_size", default_to_square=True)
|
| 277 |
+
do_rescale = do_rescale if do_rescale is not None else self.do_rescale
|
| 278 |
+
rescale_factor = rescale_factor if rescale_factor is not None else self.rescale_factor
|
| 279 |
+
do_normalize = do_normalize if do_normalize is not None else self.do_normalize
|
| 280 |
+
image_mean = image_mean if image_mean is not None else self.image_mean
|
| 281 |
+
image_std = image_std if image_std is not None else self.image_std
|
| 282 |
+
do_convert_rgb = do_convert_rgb if do_convert_rgb is not None else self.do_convert_rgb
|
| 283 |
+
|
| 284 |
+
validate_kwargs(captured_kwargs=kwargs.keys(), valid_processor_keys=self._valid_processor_keys)
|
| 285 |
+
|
| 286 |
+
images = make_flat_list_of_images(images)
|
| 287 |
+
|
| 288 |
+
if not valid_images(images):
|
| 289 |
+
raise ValueError(
|
| 290 |
+
"Invalid image type. Must be of type PIL.Image.Image, numpy.ndarray, "
|
| 291 |
+
"torch.Tensor, tf.Tensor or jax.ndarray."
|
| 292 |
+
)
|
| 293 |
+
validate_preprocess_arguments(
|
| 294 |
+
do_rescale=do_rescale,
|
| 295 |
+
rescale_factor=rescale_factor,
|
| 296 |
+
do_normalize=do_normalize,
|
| 297 |
+
image_mean=image_mean,
|
| 298 |
+
image_std=image_std,
|
| 299 |
+
do_center_crop=do_center_crop,
|
| 300 |
+
crop_size=crop_size,
|
| 301 |
+
do_resize=do_resize,
|
| 302 |
+
size=size,
|
| 303 |
+
resample=resample,
|
| 304 |
+
)
|
| 305 |
+
|
| 306 |
+
if do_convert_rgb:
|
| 307 |
+
images = [convert_to_rgb(image) for image in images]
|
| 308 |
+
|
| 309 |
+
# All transformations expect numpy arrays.
|
| 310 |
+
images = [to_numpy_array(image) for image in images]
|
| 311 |
+
|
| 312 |
+
if do_rescale and is_scaled_image(images[0]):
|
| 313 |
+
logger.warning_once(
|
| 314 |
+
"It looks like you are trying to rescale already rescaled images. If the input"
|
| 315 |
+
" images have pixel values between 0 and 1, set `do_rescale=False` to avoid rescaling them again."
|
| 316 |
+
)
|
| 317 |
+
|
| 318 |
+
if input_data_format is None:
|
| 319 |
+
# We assume that all images have the same channel dimension format.
|
| 320 |
+
input_data_format = infer_channel_dimension_format(images[0])
|
| 321 |
+
|
| 322 |
+
all_images = []
|
| 323 |
+
for image in images:
|
| 324 |
+
if do_resize:
|
| 325 |
+
image = self.resize(image=image, size=size, resample=resample, input_data_format=input_data_format)
|
| 326 |
+
|
| 327 |
+
if do_center_crop:
|
| 328 |
+
image = self.center_crop(image=image, size=crop_size, input_data_format=input_data_format)
|
| 329 |
+
|
| 330 |
+
if do_rescale:
|
| 331 |
+
image = self.rescale(image=image, scale=rescale_factor, input_data_format=input_data_format)
|
| 332 |
+
|
| 333 |
+
if do_normalize:
|
| 334 |
+
image = self.normalize(
|
| 335 |
+
image=image, mean=image_mean, std=image_std, input_data_format=input_data_format
|
| 336 |
+
)
|
| 337 |
+
|
| 338 |
+
all_images.append(image)
|
| 339 |
+
images = [
|
| 340 |
+
to_channel_dimension_format(image, data_format, input_channel_dim=input_data_format)
|
| 341 |
+
for image in all_images
|
| 342 |
+
]
|
| 343 |
+
|
| 344 |
+
data = {"pixel_values": images}
|
| 345 |
+
return BatchFeature(data=data, tensor_type=return_tensors)
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
__all__ = ["CLIPImageProcessor"]
|
lib/python3.12/site-packages/transformers/models/clip/image_processing_clip_fast.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 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 |
+
"""Fast Image processor class for CLIP."""
|
| 16 |
+
|
| 17 |
+
from ...image_processing_utils_fast import BASE_IMAGE_PROCESSOR_FAST_DOCSTRING, BaseImageProcessorFast
|
| 18 |
+
from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling
|
| 19 |
+
from ...utils import add_start_docstrings
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@add_start_docstrings(
|
| 23 |
+
"Constructs a fast CLIP image processor.",
|
| 24 |
+
BASE_IMAGE_PROCESSOR_FAST_DOCSTRING,
|
| 25 |
+
)
|
| 26 |
+
class CLIPImageProcessorFast(BaseImageProcessorFast):
|
| 27 |
+
# To be checked against the slow image processor
|
| 28 |
+
# None values left after checking can be removed
|
| 29 |
+
resample = PILImageResampling.BICUBIC
|
| 30 |
+
image_mean = OPENAI_CLIP_MEAN
|
| 31 |
+
image_std = OPENAI_CLIP_STD
|
| 32 |
+
size = {"shortest_edge": 224}
|
| 33 |
+
default_to_square = False
|
| 34 |
+
crop_size = {"height": 224, "width": 224}
|
| 35 |
+
do_resize = True
|
| 36 |
+
do_center_crop = True
|
| 37 |
+
do_rescale = True
|
| 38 |
+
do_normalize = True
|
| 39 |
+
do_convert_rgb = True
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
__all__ = ["CLIPImageProcessorFast"]
|
lib/python3.12/site-packages/transformers/models/clip/modeling_clip.py
ADDED
|
@@ -0,0 +1,1645 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2021 The OpenAI Team Authors and The HuggingFace Team. All rights reserved.
|
| 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 |
+
"""PyTorch CLIP model."""
|
| 16 |
+
|
| 17 |
+
from dataclasses import dataclass
|
| 18 |
+
from typing import Any, Optional, Tuple
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
import torch.utils.checkpoint
|
| 22 |
+
from torch import nn
|
| 23 |
+
from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss
|
| 24 |
+
|
| 25 |
+
from ...activations import ACT2FN
|
| 26 |
+
from ...modeling_attn_mask_utils import _create_4d_causal_attention_mask, _prepare_4d_attention_mask
|
| 27 |
+
from ...modeling_flash_attention_utils import flash_attn_supports_top_left_mask, is_flash_attn_available
|
| 28 |
+
from ...modeling_outputs import BaseModelOutput, BaseModelOutputWithPooling, ImageClassifierOutput
|
| 29 |
+
from ...modeling_utils import PreTrainedModel
|
| 30 |
+
from ...pytorch_utils import is_torch_greater_or_equal_than_2_2
|
| 31 |
+
from ...utils import (
|
| 32 |
+
ModelOutput,
|
| 33 |
+
add_code_sample_docstrings,
|
| 34 |
+
add_start_docstrings,
|
| 35 |
+
add_start_docstrings_to_model_forward,
|
| 36 |
+
can_return_tuple,
|
| 37 |
+
logging,
|
| 38 |
+
replace_return_docstrings,
|
| 39 |
+
torch_int,
|
| 40 |
+
)
|
| 41 |
+
from .configuration_clip import CLIPConfig, CLIPTextConfig, CLIPVisionConfig
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
if is_flash_attn_available():
|
| 45 |
+
from ...modeling_flash_attention_utils import _flash_attention_forward
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
logger = logging.get_logger(__name__)
|
| 49 |
+
|
| 50 |
+
# General docstring
|
| 51 |
+
_CONFIG_FOR_DOC = "CLIPConfig"
|
| 52 |
+
_CHECKPOINT_FOR_DOC = "openai/clip-vit-base-patch32"
|
| 53 |
+
|
| 54 |
+
# Image classification docstring
|
| 55 |
+
_IMAGE_CLASS_CHECKPOINT = "openai/clip-vit-base-patch32"
|
| 56 |
+
_IMAGE_CLASS_EXPECTED_OUTPUT = "LABEL_0"
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
# contrastive loss function, adapted from
|
| 60 |
+
# https://sachinruk.github.io/blog/2021-03-07-clip.html
|
| 61 |
+
def contrastive_loss(logits: torch.Tensor) -> torch.Tensor:
|
| 62 |
+
return nn.functional.cross_entropy(logits, torch.arange(len(logits), device=logits.device))
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def clip_loss(similarity: torch.Tensor) -> torch.Tensor:
|
| 66 |
+
caption_loss = contrastive_loss(similarity)
|
| 67 |
+
image_loss = contrastive_loss(similarity.t())
|
| 68 |
+
return (caption_loss + image_loss) / 2.0
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def _get_vector_norm(tensor: torch.Tensor) -> torch.Tensor:
|
| 72 |
+
"""
|
| 73 |
+
This method is equivalent to tensor.norm(p=2, dim=-1, keepdim=True) and used to make
|
| 74 |
+
model `executorch` exportable. See issue https://github.com/pytorch/executorch/issues/3566
|
| 75 |
+
"""
|
| 76 |
+
square_tensor = torch.pow(tensor, 2)
|
| 77 |
+
sum_tensor = torch.sum(square_tensor, dim=-1, keepdim=True)
|
| 78 |
+
normed_tensor = torch.pow(sum_tensor, 0.5)
|
| 79 |
+
return normed_tensor
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
@dataclass
|
| 83 |
+
class CLIPVisionModelOutput(ModelOutput):
|
| 84 |
+
"""
|
| 85 |
+
Base class for vision model's outputs that also contains image embeddings of the pooling of the last hidden states.
|
| 86 |
+
|
| 87 |
+
Args:
|
| 88 |
+
image_embeds (`torch.FloatTensor` of shape `(batch_size, output_dim)` *optional* returned when model is initialized with `with_projection=True`):
|
| 89 |
+
The image embeddings obtained by applying the projection layer to the pooler_output.
|
| 90 |
+
last_hidden_state (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 91 |
+
Sequence of hidden-states at the output of the last layer of the model.
|
| 92 |
+
hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
|
| 93 |
+
Tuple of `torch.FloatTensor` (one for the output of the embeddings, if the model has an embedding layer, +
|
| 94 |
+
one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.
|
| 95 |
+
|
| 96 |
+
Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.
|
| 97 |
+
attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
|
| 98 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 99 |
+
sequence_length)`.
|
| 100 |
+
|
| 101 |
+
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
| 102 |
+
heads.
|
| 103 |
+
"""
|
| 104 |
+
|
| 105 |
+
image_embeds: Optional[torch.FloatTensor] = None
|
| 106 |
+
last_hidden_state: Optional[torch.FloatTensor] = None
|
| 107 |
+
hidden_states: Optional[Tuple[torch.FloatTensor, ...]] = None
|
| 108 |
+
attentions: Optional[Tuple[torch.FloatTensor, ...]] = None
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
@dataclass
|
| 112 |
+
class CLIPTextModelOutput(ModelOutput):
|
| 113 |
+
"""
|
| 114 |
+
Base class for text model's outputs that also contains a pooling of the last hidden states.
|
| 115 |
+
|
| 116 |
+
Args:
|
| 117 |
+
text_embeds (`torch.FloatTensor` of shape `(batch_size, output_dim)` *optional* returned when model is initialized with `with_projection=True`):
|
| 118 |
+
The text embeddings obtained by applying the projection layer to the pooler_output.
|
| 119 |
+
last_hidden_state (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 120 |
+
Sequence of hidden-states at the output of the last layer of the model.
|
| 121 |
+
hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
|
| 122 |
+
Tuple of `torch.FloatTensor` (one for the output of the embeddings, if the model has an embedding layer, +
|
| 123 |
+
one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.
|
| 124 |
+
|
| 125 |
+
Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.
|
| 126 |
+
attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
|
| 127 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 128 |
+
sequence_length)`.
|
| 129 |
+
|
| 130 |
+
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
| 131 |
+
heads.
|
| 132 |
+
"""
|
| 133 |
+
|
| 134 |
+
text_embeds: Optional[torch.FloatTensor] = None
|
| 135 |
+
last_hidden_state: Optional[torch.FloatTensor] = None
|
| 136 |
+
hidden_states: Optional[Tuple[torch.FloatTensor, ...]] = None
|
| 137 |
+
attentions: Optional[Tuple[torch.FloatTensor, ...]] = None
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
@dataclass
|
| 141 |
+
class CLIPOutput(ModelOutput):
|
| 142 |
+
"""
|
| 143 |
+
Args:
|
| 144 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `return_loss` is `True`):
|
| 145 |
+
Contrastive loss for image-text similarity.
|
| 146 |
+
logits_per_image (`torch.FloatTensor` of shape `(image_batch_size, text_batch_size)`):
|
| 147 |
+
The scaled dot product scores between `image_embeds` and `text_embeds`. This represents the image-text
|
| 148 |
+
similarity scores.
|
| 149 |
+
logits_per_text (`torch.FloatTensor` of shape `(text_batch_size, image_batch_size)`):
|
| 150 |
+
The scaled dot product scores between `text_embeds` and `image_embeds`. This represents the text-image
|
| 151 |
+
similarity scores.
|
| 152 |
+
text_embeds (`torch.FloatTensor` of shape `(batch_size, output_dim`):
|
| 153 |
+
The text embeddings obtained by applying the projection layer to the pooled output of [`CLIPTextModel`].
|
| 154 |
+
image_embeds (`torch.FloatTensor` of shape `(batch_size, output_dim`):
|
| 155 |
+
The image embeddings obtained by applying the projection layer to the pooled output of [`CLIPVisionModel`].
|
| 156 |
+
text_model_output (`BaseModelOutputWithPooling`):
|
| 157 |
+
The output of the [`CLIPTextModel`].
|
| 158 |
+
vision_model_output (`BaseModelOutputWithPooling`):
|
| 159 |
+
The output of the [`CLIPVisionModel`].
|
| 160 |
+
"""
|
| 161 |
+
|
| 162 |
+
loss: Optional[torch.FloatTensor] = None
|
| 163 |
+
logits_per_image: Optional[torch.FloatTensor] = None
|
| 164 |
+
logits_per_text: Optional[torch.FloatTensor] = None
|
| 165 |
+
text_embeds: Optional[torch.FloatTensor] = None
|
| 166 |
+
image_embeds: Optional[torch.FloatTensor] = None
|
| 167 |
+
text_model_output: BaseModelOutputWithPooling = None
|
| 168 |
+
vision_model_output: BaseModelOutputWithPooling = None
|
| 169 |
+
|
| 170 |
+
def to_tuple(self) -> Tuple[Any]:
|
| 171 |
+
return tuple(
|
| 172 |
+
self[k] if k not in ["text_model_output", "vision_model_output"] else getattr(self, k).to_tuple()
|
| 173 |
+
for k in self.keys()
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
class CLIPVisionEmbeddings(nn.Module):
|
| 178 |
+
def __init__(self, config: CLIPVisionConfig):
|
| 179 |
+
super().__init__()
|
| 180 |
+
self.config = config
|
| 181 |
+
self.embed_dim = config.hidden_size
|
| 182 |
+
self.image_size = config.image_size
|
| 183 |
+
self.patch_size = config.patch_size
|
| 184 |
+
|
| 185 |
+
self.class_embedding = nn.Parameter(torch.randn(self.embed_dim))
|
| 186 |
+
|
| 187 |
+
self.patch_embedding = nn.Conv2d(
|
| 188 |
+
in_channels=config.num_channels,
|
| 189 |
+
out_channels=self.embed_dim,
|
| 190 |
+
kernel_size=self.patch_size,
|
| 191 |
+
stride=self.patch_size,
|
| 192 |
+
bias=False,
|
| 193 |
+
)
|
| 194 |
+
|
| 195 |
+
self.num_patches = (self.image_size // self.patch_size) ** 2
|
| 196 |
+
self.num_positions = self.num_patches + 1
|
| 197 |
+
self.position_embedding = nn.Embedding(self.num_positions, self.embed_dim)
|
| 198 |
+
self.register_buffer("position_ids", torch.arange(self.num_positions).expand((1, -1)), persistent=False)
|
| 199 |
+
|
| 200 |
+
def interpolate_pos_encoding(self, embeddings: torch.Tensor, height: int, width: int) -> torch.Tensor:
|
| 201 |
+
"""
|
| 202 |
+
This method allows to interpolate the pre-trained position encodings, to be able to use the model on higher resolution
|
| 203 |
+
images. This method is also adapted to support torch.jit tracing.
|
| 204 |
+
|
| 205 |
+
Adapted from:
|
| 206 |
+
- https://github.com/facebookresearch/dino/blob/de9ee3df6cf39fac952ab558447af1fa1365362a/vision_transformer.py#L174-L194, and
|
| 207 |
+
- https://github.com/facebookresearch/dinov2/blob/e1277af2ba9496fbadf7aec6eba56e8d882d1e35/dinov2/models/vision_transformer.py#L179-L211
|
| 208 |
+
"""
|
| 209 |
+
|
| 210 |
+
num_patches = embeddings.shape[1] - 1
|
| 211 |
+
position_embedding = self.position_embedding.weight.unsqueeze(0)
|
| 212 |
+
num_positions = position_embedding.shape[1] - 1
|
| 213 |
+
|
| 214 |
+
# always interpolate when tracing to ensure the exported model works for dynamic input shapes
|
| 215 |
+
if not torch.jit.is_tracing() and num_patches == num_positions and height == width:
|
| 216 |
+
return self.position_embedding(self.position_ids)
|
| 217 |
+
|
| 218 |
+
class_pos_embed = position_embedding[:, :1]
|
| 219 |
+
patch_pos_embed = position_embedding[:, 1:]
|
| 220 |
+
|
| 221 |
+
dim = embeddings.shape[-1]
|
| 222 |
+
|
| 223 |
+
new_height = height // self.patch_size
|
| 224 |
+
new_width = width // self.patch_size
|
| 225 |
+
|
| 226 |
+
sqrt_num_positions = torch_int(num_positions**0.5)
|
| 227 |
+
patch_pos_embed = patch_pos_embed.reshape(1, sqrt_num_positions, sqrt_num_positions, dim)
|
| 228 |
+
patch_pos_embed = patch_pos_embed.permute(0, 3, 1, 2)
|
| 229 |
+
|
| 230 |
+
patch_pos_embed = nn.functional.interpolate(
|
| 231 |
+
patch_pos_embed,
|
| 232 |
+
size=(new_height, new_width),
|
| 233 |
+
mode="bicubic",
|
| 234 |
+
align_corners=False,
|
| 235 |
+
)
|
| 236 |
+
|
| 237 |
+
patch_pos_embed = patch_pos_embed.permute(0, 2, 3, 1).view(1, -1, dim)
|
| 238 |
+
|
| 239 |
+
return torch.cat((class_pos_embed, patch_pos_embed), dim=1)
|
| 240 |
+
|
| 241 |
+
def forward(self, pixel_values: torch.FloatTensor, interpolate_pos_encoding=False) -> torch.Tensor:
|
| 242 |
+
batch_size, _, height, width = pixel_values.shape
|
| 243 |
+
if not interpolate_pos_encoding and (height != self.image_size or width != self.image_size):
|
| 244 |
+
raise ValueError(
|
| 245 |
+
f"Input image size ({height}*{width}) doesn't match model ({self.image_size}*{self.image_size})."
|
| 246 |
+
)
|
| 247 |
+
target_dtype = self.patch_embedding.weight.dtype
|
| 248 |
+
patch_embeds = self.patch_embedding(pixel_values.to(dtype=target_dtype)) # shape = [*, width, grid, grid]
|
| 249 |
+
patch_embeds = patch_embeds.flatten(2).transpose(1, 2)
|
| 250 |
+
|
| 251 |
+
class_embeds = self.class_embedding.expand(batch_size, 1, -1)
|
| 252 |
+
embeddings = torch.cat([class_embeds, patch_embeds], dim=1)
|
| 253 |
+
if interpolate_pos_encoding:
|
| 254 |
+
embeddings = embeddings + self.interpolate_pos_encoding(embeddings, height, width)
|
| 255 |
+
else:
|
| 256 |
+
embeddings = embeddings + self.position_embedding(self.position_ids)
|
| 257 |
+
return embeddings
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
class CLIPTextEmbeddings(nn.Module):
|
| 261 |
+
def __init__(self, config: CLIPTextConfig):
|
| 262 |
+
super().__init__()
|
| 263 |
+
embed_dim = config.hidden_size
|
| 264 |
+
|
| 265 |
+
self.token_embedding = nn.Embedding(config.vocab_size, embed_dim)
|
| 266 |
+
self.position_embedding = nn.Embedding(config.max_position_embeddings, embed_dim)
|
| 267 |
+
|
| 268 |
+
# position_ids (1, len position emb) is contiguous in memory and exported when serialized
|
| 269 |
+
self.register_buffer(
|
| 270 |
+
"position_ids", torch.arange(config.max_position_embeddings).expand((1, -1)), persistent=False
|
| 271 |
+
)
|
| 272 |
+
|
| 273 |
+
def forward(
|
| 274 |
+
self,
|
| 275 |
+
input_ids: Optional[torch.LongTensor] = None,
|
| 276 |
+
position_ids: Optional[torch.LongTensor] = None,
|
| 277 |
+
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 278 |
+
) -> torch.Tensor:
|
| 279 |
+
seq_length = input_ids.shape[-1] if input_ids is not None else inputs_embeds.shape[-2]
|
| 280 |
+
max_position_embedding = self.position_embedding.weight.shape[0]
|
| 281 |
+
|
| 282 |
+
if seq_length > max_position_embedding:
|
| 283 |
+
raise ValueError(
|
| 284 |
+
f"Sequence length must be less than max_position_embeddings (got `sequence length`: "
|
| 285 |
+
f"{seq_length} and max_position_embeddings: {max_position_embedding}"
|
| 286 |
+
)
|
| 287 |
+
|
| 288 |
+
if position_ids is None:
|
| 289 |
+
position_ids = self.position_ids[:, :seq_length]
|
| 290 |
+
|
| 291 |
+
if inputs_embeds is None:
|
| 292 |
+
inputs_embeds = self.token_embedding(input_ids)
|
| 293 |
+
|
| 294 |
+
position_embeddings = self.position_embedding(position_ids)
|
| 295 |
+
embeddings = inputs_embeds + position_embeddings
|
| 296 |
+
|
| 297 |
+
return embeddings
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
class CLIPAttention(nn.Module):
|
| 301 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 302 |
+
|
| 303 |
+
def __init__(self, config):
|
| 304 |
+
super().__init__()
|
| 305 |
+
self.config = config
|
| 306 |
+
self.embed_dim = config.hidden_size
|
| 307 |
+
self.num_heads = config.num_attention_heads
|
| 308 |
+
self.head_dim = self.embed_dim // self.num_heads
|
| 309 |
+
if self.head_dim * self.num_heads != self.embed_dim:
|
| 310 |
+
raise ValueError(
|
| 311 |
+
f"embed_dim must be divisible by num_heads (got `embed_dim`: {self.embed_dim} and `num_heads`:"
|
| 312 |
+
f" {self.num_heads})."
|
| 313 |
+
)
|
| 314 |
+
self.scale = self.head_dim**-0.5
|
| 315 |
+
self.dropout = config.attention_dropout
|
| 316 |
+
|
| 317 |
+
self.k_proj = nn.Linear(self.embed_dim, self.embed_dim)
|
| 318 |
+
self.v_proj = nn.Linear(self.embed_dim, self.embed_dim)
|
| 319 |
+
self.q_proj = nn.Linear(self.embed_dim, self.embed_dim)
|
| 320 |
+
self.out_proj = nn.Linear(self.embed_dim, self.embed_dim)
|
| 321 |
+
|
| 322 |
+
def _shape(self, tensor: torch.Tensor, seq_len: int, bsz: int):
|
| 323 |
+
return tensor.view(bsz, seq_len, self.num_heads, self.head_dim).transpose(1, 2).contiguous()
|
| 324 |
+
|
| 325 |
+
def forward(
|
| 326 |
+
self,
|
| 327 |
+
hidden_states: torch.Tensor,
|
| 328 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 329 |
+
causal_attention_mask: Optional[torch.Tensor] = None,
|
| 330 |
+
output_attentions: Optional[bool] = False,
|
| 331 |
+
) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
|
| 332 |
+
"""Input shape: Batch x Time x Channel"""
|
| 333 |
+
|
| 334 |
+
bsz, tgt_len, embed_dim = hidden_states.size()
|
| 335 |
+
|
| 336 |
+
# get query proj
|
| 337 |
+
query_states = self.q_proj(hidden_states) * self.scale
|
| 338 |
+
key_states = self._shape(self.k_proj(hidden_states), -1, bsz)
|
| 339 |
+
value_states = self._shape(self.v_proj(hidden_states), -1, bsz)
|
| 340 |
+
|
| 341 |
+
proj_shape = (bsz * self.num_heads, -1, self.head_dim)
|
| 342 |
+
query_states = self._shape(query_states, tgt_len, bsz).view(*proj_shape)
|
| 343 |
+
key_states = key_states.view(*proj_shape)
|
| 344 |
+
value_states = value_states.view(*proj_shape)
|
| 345 |
+
|
| 346 |
+
src_len = key_states.size(1)
|
| 347 |
+
attn_weights = torch.bmm(query_states, key_states.transpose(1, 2))
|
| 348 |
+
|
| 349 |
+
if attn_weights.size() != (bsz * self.num_heads, tgt_len, src_len):
|
| 350 |
+
raise ValueError(
|
| 351 |
+
f"Attention weights should be of size {(bsz * self.num_heads, tgt_len, src_len)}, but is"
|
| 352 |
+
f" {attn_weights.size()}"
|
| 353 |
+
)
|
| 354 |
+
|
| 355 |
+
# apply the causal_attention_mask first
|
| 356 |
+
if causal_attention_mask is not None:
|
| 357 |
+
if causal_attention_mask.size() != (bsz, 1, tgt_len, src_len):
|
| 358 |
+
raise ValueError(
|
| 359 |
+
f"Attention mask should be of size {(bsz, 1, tgt_len, src_len)}, but is"
|
| 360 |
+
f" {causal_attention_mask.size()}"
|
| 361 |
+
)
|
| 362 |
+
attn_weights = attn_weights.view(bsz, self.num_heads, tgt_len, src_len) + causal_attention_mask
|
| 363 |
+
attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len)
|
| 364 |
+
|
| 365 |
+
if attention_mask is not None:
|
| 366 |
+
if attention_mask.size() != (bsz, 1, tgt_len, src_len):
|
| 367 |
+
raise ValueError(
|
| 368 |
+
f"Attention mask should be of size {(bsz, 1, tgt_len, src_len)}, but is {attention_mask.size()}"
|
| 369 |
+
)
|
| 370 |
+
attn_weights = attn_weights.view(bsz, self.num_heads, tgt_len, src_len) + attention_mask
|
| 371 |
+
attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len)
|
| 372 |
+
|
| 373 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1)
|
| 374 |
+
|
| 375 |
+
if output_attentions:
|
| 376 |
+
# this operation is a bit awkward, but it's required to
|
| 377 |
+
# make sure that attn_weights keeps its gradient.
|
| 378 |
+
# In order to do so, attn_weights have to reshaped
|
| 379 |
+
# twice and have to be reused in the following
|
| 380 |
+
attn_weights_reshaped = attn_weights.view(bsz, self.num_heads, tgt_len, src_len)
|
| 381 |
+
attn_weights = attn_weights_reshaped.view(bsz * self.num_heads, tgt_len, src_len)
|
| 382 |
+
else:
|
| 383 |
+
attn_weights_reshaped = None
|
| 384 |
+
|
| 385 |
+
attn_probs = nn.functional.dropout(attn_weights, p=self.dropout, training=self.training)
|
| 386 |
+
|
| 387 |
+
attn_output = torch.bmm(attn_probs, value_states)
|
| 388 |
+
|
| 389 |
+
if attn_output.size() != (bsz * self.num_heads, tgt_len, self.head_dim):
|
| 390 |
+
raise ValueError(
|
| 391 |
+
f"`attn_output` should be of size {(bsz, self.num_heads, tgt_len, self.head_dim)}, but is"
|
| 392 |
+
f" {attn_output.size()}"
|
| 393 |
+
)
|
| 394 |
+
|
| 395 |
+
attn_output = attn_output.view(bsz, self.num_heads, tgt_len, self.head_dim)
|
| 396 |
+
attn_output = attn_output.transpose(1, 2)
|
| 397 |
+
attn_output = attn_output.reshape(bsz, tgt_len, embed_dim)
|
| 398 |
+
|
| 399 |
+
attn_output = self.out_proj(attn_output)
|
| 400 |
+
|
| 401 |
+
return attn_output, attn_weights_reshaped
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
class CLIPFlashAttention2(CLIPAttention):
|
| 405 |
+
"""
|
| 406 |
+
CLIPAttention flash attention module. This module inherits from `CLIPAttention` as the weights of the module stays
|
| 407 |
+
untouched. The only required change would be on the forward pass where it needs to correctly call the public API of
|
| 408 |
+
flash attention and deal with padding tokens in case the input contains any of them.
|
| 409 |
+
"""
|
| 410 |
+
|
| 411 |
+
def __init__(self, *args, **kwargs):
|
| 412 |
+
super().__init__(*args, **kwargs)
|
| 413 |
+
|
| 414 |
+
# TODO: Should be removed once Flash Attention for RoCm is bumped to 2.1.
|
| 415 |
+
# flash_attn<2.1 generates top-left aligned causal mask, while what is needed here is bottom-right alignment, that was made default for flash_attn>=2.1. This attribute is used to handle this difference. Reference: https://github.com/Dao-AILab/flash-attention/releases/tag/v2.1.0.
|
| 416 |
+
# Beware that with flash_attn<2.1, using q_seqlen != k_seqlen (except for the case q_seqlen == 1) produces a wrong mask (top-left).
|
| 417 |
+
self._flash_attn_uses_top_left_mask = flash_attn_supports_top_left_mask()
|
| 418 |
+
|
| 419 |
+
# Adapted from transformers.models.llama.modeling_llama.LlamaFlashAttention2.forward
|
| 420 |
+
def forward(
|
| 421 |
+
self,
|
| 422 |
+
hidden_states: torch.Tensor,
|
| 423 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 424 |
+
causal_attention_mask: Optional[torch.Tensor] = None,
|
| 425 |
+
output_attentions: Optional[bool] = False,
|
| 426 |
+
) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
|
| 427 |
+
output_attentions = False
|
| 428 |
+
|
| 429 |
+
batch_size, q_len, _ = hidden_states.size()
|
| 430 |
+
|
| 431 |
+
query_states = self.q_proj(hidden_states)
|
| 432 |
+
key_states = self.k_proj(hidden_states)
|
| 433 |
+
value_states = self.v_proj(hidden_states)
|
| 434 |
+
|
| 435 |
+
# Flash attention requires the input to have the shape
|
| 436 |
+
# batch_size x seq_length x head_dim x hidden_dim
|
| 437 |
+
# therefore we just need to keep the original shape
|
| 438 |
+
query_states = query_states.view(batch_size, q_len, self.num_heads, self.head_dim)
|
| 439 |
+
key_states = key_states.view(batch_size, q_len, self.num_heads, self.head_dim)
|
| 440 |
+
value_states = value_states.view(batch_size, q_len, self.num_heads, self.head_dim)
|
| 441 |
+
|
| 442 |
+
dropout_rate = self.dropout if self.training else 0.0
|
| 443 |
+
|
| 444 |
+
# In PEFT, usually we cast the layer norms in float32 for training stability reasons
|
| 445 |
+
# therefore the input hidden states gets silently casted in float32. Hence, we need
|
| 446 |
+
# cast them back in the correct dtype just to be sure everything works as expected.
|
| 447 |
+
# This might slowdown training & inference so it is recommended to not cast the LayerNorms
|
| 448 |
+
# in fp32.
|
| 449 |
+
|
| 450 |
+
input_dtype = query_states.dtype
|
| 451 |
+
if input_dtype == torch.float32:
|
| 452 |
+
if torch.is_autocast_enabled():
|
| 453 |
+
target_dtype = torch.get_autocast_gpu_dtype()
|
| 454 |
+
# Handle the case where the model is quantized
|
| 455 |
+
elif hasattr(self.config, "_pre_quantization_dtype"):
|
| 456 |
+
target_dtype = self.config._pre_quantization_dtype
|
| 457 |
+
else:
|
| 458 |
+
target_dtype = self.q_proj.weight.dtype
|
| 459 |
+
|
| 460 |
+
logger.warning_once(
|
| 461 |
+
f"The input hidden states seems to be silently casted in float32, this might be related to"
|
| 462 |
+
f" the fact you have upcasted embedding or layer norm layers in float32. We will cast back the input in"
|
| 463 |
+
f" {target_dtype}."
|
| 464 |
+
)
|
| 465 |
+
|
| 466 |
+
query_states = query_states.to(target_dtype)
|
| 467 |
+
key_states = key_states.to(target_dtype)
|
| 468 |
+
value_states = value_states.to(target_dtype)
|
| 469 |
+
|
| 470 |
+
attn_output = _flash_attention_forward(
|
| 471 |
+
query_states,
|
| 472 |
+
key_states,
|
| 473 |
+
value_states,
|
| 474 |
+
attention_mask,
|
| 475 |
+
q_len,
|
| 476 |
+
dropout=dropout_rate,
|
| 477 |
+
is_causal=causal_attention_mask is not None,
|
| 478 |
+
use_top_left_mask=self._flash_attn_uses_top_left_mask,
|
| 479 |
+
)
|
| 480 |
+
|
| 481 |
+
attn_output = attn_output.reshape(batch_size, q_len, self.embed_dim).contiguous()
|
| 482 |
+
attn_output = self.out_proj(attn_output)
|
| 483 |
+
|
| 484 |
+
if not output_attentions:
|
| 485 |
+
attn_weights = None
|
| 486 |
+
|
| 487 |
+
return attn_output, attn_weights
|
| 488 |
+
|
| 489 |
+
|
| 490 |
+
class CLIPSdpaAttention(CLIPAttention):
|
| 491 |
+
"""
|
| 492 |
+
SDPA attention module using torch.nn.functional.scaled_dot_product_attention. This module inherits from
|
| 493 |
+
`CLIPAttention` as the weights of the module stays untouched. The only changes are on the forward pass to adapt to
|
| 494 |
+
SDPA API.
|
| 495 |
+
"""
|
| 496 |
+
|
| 497 |
+
# Adapted from CLIPAttention.forward
|
| 498 |
+
def forward(
|
| 499 |
+
self,
|
| 500 |
+
hidden_states: torch.Tensor,
|
| 501 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 502 |
+
causal_attention_mask: Optional[torch.Tensor] = None,
|
| 503 |
+
output_attentions: Optional[bool] = False,
|
| 504 |
+
) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
|
| 505 |
+
if output_attentions:
|
| 506 |
+
# TODO: Improve this warning with e.g. `model.config.attn_implementation = "manual"` once this is implemented.
|
| 507 |
+
logger.warning_once(
|
| 508 |
+
"CLIPModel is using CLIPSdpaAttention, but `torch.nn.functional.scaled_dot_product_attention` does not "
|
| 509 |
+
"support `output_attentions=True`. Falling back to the manual attention implementation, but specifying "
|
| 510 |
+
"the manual implementation will be required from Transformers version v5.0.0 onwards. This warning can "
|
| 511 |
+
'be removed using the argument `attn_implementation="eager"` when loading the model.'
|
| 512 |
+
)
|
| 513 |
+
return super().forward(
|
| 514 |
+
hidden_states=hidden_states,
|
| 515 |
+
attention_mask=attention_mask,
|
| 516 |
+
causal_attention_mask=causal_attention_mask,
|
| 517 |
+
output_attentions=output_attentions,
|
| 518 |
+
)
|
| 519 |
+
|
| 520 |
+
# CLIP text model uses both `causal_attention_mask` and `attention_mask`
|
| 521 |
+
if attention_mask is not None and causal_attention_mask is not None:
|
| 522 |
+
attn_mask = attention_mask + causal_attention_mask
|
| 523 |
+
elif causal_attention_mask is not None:
|
| 524 |
+
attn_mask = causal_attention_mask
|
| 525 |
+
else:
|
| 526 |
+
attn_mask = attention_mask
|
| 527 |
+
|
| 528 |
+
bsz, tgt_len, embed_dim = hidden_states.size()
|
| 529 |
+
|
| 530 |
+
query_states = self.q_proj(hidden_states)
|
| 531 |
+
key_states = self.k_proj(hidden_states)
|
| 532 |
+
value_states = self.v_proj(hidden_states)
|
| 533 |
+
|
| 534 |
+
query_states = query_states.view(bsz, -1, self.num_heads, self.head_dim).transpose(1, 2)
|
| 535 |
+
key_states = key_states.view(bsz, -1, self.num_heads, self.head_dim).transpose(1, 2)
|
| 536 |
+
value_states = value_states.view(bsz, -1, self.num_heads, self.head_dim).transpose(1, 2)
|
| 537 |
+
|
| 538 |
+
# SDPA with memory-efficient backend is currently (torch==2.1.2) bugged with non-contiguous inputs with custom attn_mask,
|
| 539 |
+
# Reference: https://github.com/pytorch/pytorch/issues/112577.
|
| 540 |
+
if not is_torch_greater_or_equal_than_2_2 and query_states.device.type == "cuda" and attn_mask is not None:
|
| 541 |
+
query_states = query_states.contiguous()
|
| 542 |
+
key_states = key_states.contiguous()
|
| 543 |
+
value_states = value_states.contiguous()
|
| 544 |
+
|
| 545 |
+
# CLIP text model uses both `causal_attention_mask` and `attention_mask` sequentially.
|
| 546 |
+
attn_output = torch.nn.functional.scaled_dot_product_attention(
|
| 547 |
+
query_states,
|
| 548 |
+
key_states,
|
| 549 |
+
value_states,
|
| 550 |
+
attn_mask=attn_mask,
|
| 551 |
+
dropout_p=self.dropout if self.training else 0.0,
|
| 552 |
+
scale=self.scale,
|
| 553 |
+
)
|
| 554 |
+
|
| 555 |
+
attn_output = attn_output.transpose(1, 2)
|
| 556 |
+
attn_output = attn_output.reshape(bsz, tgt_len, embed_dim)
|
| 557 |
+
|
| 558 |
+
attn_output = self.out_proj(attn_output)
|
| 559 |
+
|
| 560 |
+
return attn_output, None
|
| 561 |
+
|
| 562 |
+
|
| 563 |
+
CLIP_ATTENTION_CLASSES = {
|
| 564 |
+
"eager": CLIPAttention,
|
| 565 |
+
"sdpa": CLIPSdpaAttention,
|
| 566 |
+
"flash_attention_2": CLIPFlashAttention2,
|
| 567 |
+
}
|
| 568 |
+
|
| 569 |
+
|
| 570 |
+
class CLIPMLP(nn.Module):
|
| 571 |
+
def __init__(self, config):
|
| 572 |
+
super().__init__()
|
| 573 |
+
self.config = config
|
| 574 |
+
self.activation_fn = ACT2FN[config.hidden_act]
|
| 575 |
+
self.fc1 = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 576 |
+
self.fc2 = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 577 |
+
|
| 578 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 579 |
+
hidden_states = self.fc1(hidden_states)
|
| 580 |
+
hidden_states = self.activation_fn(hidden_states)
|
| 581 |
+
hidden_states = self.fc2(hidden_states)
|
| 582 |
+
return hidden_states
|
| 583 |
+
|
| 584 |
+
|
| 585 |
+
class CLIPEncoderLayer(nn.Module):
|
| 586 |
+
def __init__(self, config: CLIPConfig):
|
| 587 |
+
super().__init__()
|
| 588 |
+
self.embed_dim = config.hidden_size
|
| 589 |
+
self.self_attn = CLIP_ATTENTION_CLASSES[config._attn_implementation](config)
|
| 590 |
+
self.layer_norm1 = nn.LayerNorm(self.embed_dim, eps=config.layer_norm_eps)
|
| 591 |
+
self.mlp = CLIPMLP(config)
|
| 592 |
+
self.layer_norm2 = nn.LayerNorm(self.embed_dim, eps=config.layer_norm_eps)
|
| 593 |
+
|
| 594 |
+
def forward(
|
| 595 |
+
self,
|
| 596 |
+
hidden_states: torch.Tensor,
|
| 597 |
+
attention_mask: torch.Tensor,
|
| 598 |
+
causal_attention_mask: torch.Tensor,
|
| 599 |
+
output_attentions: Optional[bool] = False,
|
| 600 |
+
) -> Tuple[torch.FloatTensor]:
|
| 601 |
+
"""
|
| 602 |
+
Args:
|
| 603 |
+
hidden_states (`torch.FloatTensor`): input to the layer of shape `(batch, seq_len, embed_dim)`
|
| 604 |
+
attention_mask (`torch.FloatTensor`): attention mask of size
|
| 605 |
+
`(batch, 1, tgt_len, src_len)` where padding elements are indicated by very large negative values.
|
| 606 |
+
`(config.encoder_attention_heads,)`.
|
| 607 |
+
output_attentions (`bool`, *optional*):
|
| 608 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under
|
| 609 |
+
returned tensors for more detail.
|
| 610 |
+
"""
|
| 611 |
+
residual = hidden_states
|
| 612 |
+
|
| 613 |
+
hidden_states = self.layer_norm1(hidden_states)
|
| 614 |
+
hidden_states, attn_weights = self.self_attn(
|
| 615 |
+
hidden_states=hidden_states,
|
| 616 |
+
attention_mask=attention_mask,
|
| 617 |
+
causal_attention_mask=causal_attention_mask,
|
| 618 |
+
output_attentions=output_attentions,
|
| 619 |
+
)
|
| 620 |
+
hidden_states = residual + hidden_states
|
| 621 |
+
|
| 622 |
+
residual = hidden_states
|
| 623 |
+
hidden_states = self.layer_norm2(hidden_states)
|
| 624 |
+
hidden_states = self.mlp(hidden_states)
|
| 625 |
+
hidden_states = residual + hidden_states
|
| 626 |
+
|
| 627 |
+
outputs = (hidden_states,)
|
| 628 |
+
|
| 629 |
+
if output_attentions:
|
| 630 |
+
outputs += (attn_weights,)
|
| 631 |
+
|
| 632 |
+
return outputs
|
| 633 |
+
|
| 634 |
+
|
| 635 |
+
class CLIPPreTrainedModel(PreTrainedModel):
|
| 636 |
+
"""
|
| 637 |
+
An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained
|
| 638 |
+
models.
|
| 639 |
+
"""
|
| 640 |
+
|
| 641 |
+
config_class = CLIPConfig
|
| 642 |
+
base_model_prefix = "clip"
|
| 643 |
+
supports_gradient_checkpointing = True
|
| 644 |
+
_supports_sdpa = True
|
| 645 |
+
_supports_flash_attn_2 = True
|
| 646 |
+
|
| 647 |
+
def _init_weights(self, module):
|
| 648 |
+
"""Initialize the weights"""
|
| 649 |
+
factor = self.config.initializer_factor
|
| 650 |
+
if isinstance(module, CLIPTextEmbeddings):
|
| 651 |
+
module.token_embedding.weight.data.normal_(mean=0.0, std=factor * 0.02)
|
| 652 |
+
module.position_embedding.weight.data.normal_(mean=0.0, std=factor * 0.02)
|
| 653 |
+
elif isinstance(module, CLIPVisionEmbeddings):
|
| 654 |
+
factor = self.config.initializer_factor
|
| 655 |
+
nn.init.normal_(module.class_embedding, mean=0.0, std=module.embed_dim**-0.5 * factor)
|
| 656 |
+
nn.init.normal_(module.patch_embedding.weight, std=module.config.initializer_range * factor)
|
| 657 |
+
nn.init.normal_(module.position_embedding.weight, std=module.config.initializer_range * factor)
|
| 658 |
+
elif isinstance(module, CLIPAttention):
|
| 659 |
+
factor = self.config.initializer_factor
|
| 660 |
+
in_proj_std = (module.embed_dim**-0.5) * ((2 * module.config.num_hidden_layers) ** -0.5) * factor
|
| 661 |
+
out_proj_std = (module.embed_dim**-0.5) * factor
|
| 662 |
+
nn.init.normal_(module.q_proj.weight, std=in_proj_std)
|
| 663 |
+
nn.init.normal_(module.k_proj.weight, std=in_proj_std)
|
| 664 |
+
nn.init.normal_(module.v_proj.weight, std=in_proj_std)
|
| 665 |
+
nn.init.normal_(module.out_proj.weight, std=out_proj_std)
|
| 666 |
+
elif isinstance(module, CLIPMLP):
|
| 667 |
+
factor = self.config.initializer_factor
|
| 668 |
+
in_proj_std = (module.config.hidden_size**-0.5) * ((2 * module.config.num_hidden_layers) ** -0.5) * factor
|
| 669 |
+
fc_std = (2 * module.config.hidden_size) ** -0.5 * factor
|
| 670 |
+
nn.init.normal_(module.fc1.weight, std=fc_std)
|
| 671 |
+
nn.init.normal_(module.fc2.weight, std=in_proj_std)
|
| 672 |
+
elif isinstance(module, CLIPModel):
|
| 673 |
+
nn.init.normal_(
|
| 674 |
+
module.text_projection.weight,
|
| 675 |
+
std=module.text_embed_dim**-0.5 * self.config.initializer_factor,
|
| 676 |
+
)
|
| 677 |
+
nn.init.normal_(
|
| 678 |
+
module.visual_projection.weight,
|
| 679 |
+
std=module.vision_embed_dim**-0.5 * self.config.initializer_factor,
|
| 680 |
+
)
|
| 681 |
+
elif isinstance(module, CLIPVisionModelWithProjection):
|
| 682 |
+
nn.init.normal_(
|
| 683 |
+
module.visual_projection.weight,
|
| 684 |
+
std=self.config.hidden_size**-0.5 * self.config.initializer_factor,
|
| 685 |
+
)
|
| 686 |
+
elif isinstance(module, CLIPTextModelWithProjection):
|
| 687 |
+
nn.init.normal_(
|
| 688 |
+
module.text_projection.weight,
|
| 689 |
+
std=self.config.hidden_size**-0.5 * self.config.initializer_factor,
|
| 690 |
+
)
|
| 691 |
+
elif isinstance(module, CLIPForImageClassification):
|
| 692 |
+
nn.init.normal_(
|
| 693 |
+
module.classifier.weight,
|
| 694 |
+
std=self.config.vision_config.hidden_size**-0.5 * self.config.initializer_factor,
|
| 695 |
+
)
|
| 696 |
+
|
| 697 |
+
if isinstance(module, nn.LayerNorm):
|
| 698 |
+
module.bias.data.zero_()
|
| 699 |
+
module.weight.data.fill_(1.0)
|
| 700 |
+
if isinstance(module, nn.Linear) and module.bias is not None:
|
| 701 |
+
module.bias.data.zero_()
|
| 702 |
+
|
| 703 |
+
|
| 704 |
+
CLIP_START_DOCSTRING = r"""
|
| 705 |
+
This model inherits from [`PreTrainedModel`]. Check the superclass documentation for the generic methods the
|
| 706 |
+
library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads
|
| 707 |
+
etc.)
|
| 708 |
+
|
| 709 |
+
This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass.
|
| 710 |
+
Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage
|
| 711 |
+
and behavior.
|
| 712 |
+
|
| 713 |
+
Parameters:
|
| 714 |
+
config ([`CLIPConfig`]): Model configuration class with all the parameters of the model.
|
| 715 |
+
Initializing with a config file does not load the weights associated with the model, only the
|
| 716 |
+
configuration. Check out the [`~PreTrainedModel.from_pretrained`] method to load the model weights.
|
| 717 |
+
"""
|
| 718 |
+
|
| 719 |
+
CLIP_TEXT_INPUTS_DOCSTRING = r"""
|
| 720 |
+
Args:
|
| 721 |
+
input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
|
| 722 |
+
Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
|
| 723 |
+
it.
|
| 724 |
+
|
| 725 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 726 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 727 |
+
|
| 728 |
+
[What are input IDs?](../glossary#input-ids)
|
| 729 |
+
attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 730 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 731 |
+
|
| 732 |
+
- 1 for tokens that are **not masked**,
|
| 733 |
+
- 0 for tokens that are **masked**.
|
| 734 |
+
|
| 735 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 736 |
+
position_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 737 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 738 |
+
config.max_position_embeddings - 1]`.
|
| 739 |
+
|
| 740 |
+
[What are position IDs?](../glossary#position-ids)
|
| 741 |
+
output_attentions (`bool`, *optional*):
|
| 742 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 743 |
+
tensors for more detail.
|
| 744 |
+
output_hidden_states (`bool`, *optional*):
|
| 745 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 746 |
+
more detail.
|
| 747 |
+
return_dict (`bool`, *optional*):
|
| 748 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 749 |
+
"""
|
| 750 |
+
|
| 751 |
+
CLIP_VISION_INPUTS_DOCSTRING = r"""
|
| 752 |
+
Args:
|
| 753 |
+
pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, height, width)`):
|
| 754 |
+
Pixel values. Padding will be ignored by default should you provide it. Pixel values can be obtained using
|
| 755 |
+
[`AutoImageProcessor`]. See [`CLIPImageProcessor.__call__`] for details.
|
| 756 |
+
output_attentions (`bool`, *optional*):
|
| 757 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 758 |
+
tensors for more detail.
|
| 759 |
+
output_hidden_states (`bool`, *optional*):
|
| 760 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 761 |
+
more detail.
|
| 762 |
+
interpolate_pos_encoding (`bool`, *optional*, defaults `False`):
|
| 763 |
+
Whether to interpolate the pre-trained position encodings.
|
| 764 |
+
return_dict (`bool`, *optional*):
|
| 765 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 766 |
+
"""
|
| 767 |
+
|
| 768 |
+
CLIP_INPUTS_DOCSTRING = r"""
|
| 769 |
+
Args:
|
| 770 |
+
input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
|
| 771 |
+
Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
|
| 772 |
+
it.
|
| 773 |
+
|
| 774 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 775 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 776 |
+
|
| 777 |
+
[What are input IDs?](../glossary#input-ids)
|
| 778 |
+
attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 779 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 780 |
+
|
| 781 |
+
- 1 for tokens that are **not masked**,
|
| 782 |
+
- 0 for tokens that are **masked**.
|
| 783 |
+
|
| 784 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 785 |
+
position_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 786 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 787 |
+
config.max_position_embeddings - 1]`.
|
| 788 |
+
|
| 789 |
+
[What are position IDs?](../glossary#position-ids)
|
| 790 |
+
pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, height, width)`):
|
| 791 |
+
Pixel values. Padding will be ignored by default should you provide it. Pixel values can be obtained using
|
| 792 |
+
[`AutoImageProcessor`]. See [`CLIPImageProcessor.__call__`] for details.
|
| 793 |
+
return_loss (`bool`, *optional*):
|
| 794 |
+
Whether or not to return the contrastive loss.
|
| 795 |
+
output_attentions (`bool`, *optional*):
|
| 796 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 797 |
+
tensors for more detail.
|
| 798 |
+
output_hidden_states (`bool`, *optional*):
|
| 799 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 800 |
+
more detail.
|
| 801 |
+
interpolate_pos_encoding (`bool`, *optional*, defaults `False`):
|
| 802 |
+
Whether to interpolate the pre-trained position encodings.
|
| 803 |
+
return_dict (`bool`, *optional*):
|
| 804 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 805 |
+
"""
|
| 806 |
+
|
| 807 |
+
|
| 808 |
+
class CLIPEncoder(nn.Module):
|
| 809 |
+
"""
|
| 810 |
+
Transformer encoder consisting of `config.num_hidden_layers` self attention layers. Each layer is a
|
| 811 |
+
[`CLIPEncoderLayer`].
|
| 812 |
+
|
| 813 |
+
Args:
|
| 814 |
+
config: CLIPConfig
|
| 815 |
+
"""
|
| 816 |
+
|
| 817 |
+
def __init__(self, config: CLIPConfig):
|
| 818 |
+
super().__init__()
|
| 819 |
+
self.config = config
|
| 820 |
+
self.layers = nn.ModuleList([CLIPEncoderLayer(config) for _ in range(config.num_hidden_layers)])
|
| 821 |
+
self.gradient_checkpointing = False
|
| 822 |
+
|
| 823 |
+
@can_return_tuple
|
| 824 |
+
def forward(
|
| 825 |
+
self,
|
| 826 |
+
inputs_embeds,
|
| 827 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 828 |
+
causal_attention_mask: Optional[torch.Tensor] = None,
|
| 829 |
+
output_attentions: Optional[bool] = None,
|
| 830 |
+
output_hidden_states: Optional[bool] = None,
|
| 831 |
+
) -> BaseModelOutput:
|
| 832 |
+
r"""
|
| 833 |
+
Args:
|
| 834 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 835 |
+
Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation.
|
| 836 |
+
This is useful if you want more control over how to convert `input_ids` indices into associated vectors
|
| 837 |
+
than the model's internal embedding lookup matrix.
|
| 838 |
+
attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 839 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 840 |
+
|
| 841 |
+
- 1 for tokens that are **not masked**,
|
| 842 |
+
- 0 for tokens that are **masked**.
|
| 843 |
+
|
| 844 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 845 |
+
causal_attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 846 |
+
Causal mask for the text model. Mask values selected in `[0, 1]`:
|
| 847 |
+
|
| 848 |
+
- 1 for tokens that are **not masked**,
|
| 849 |
+
- 0 for tokens that are **masked**.
|
| 850 |
+
|
| 851 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 852 |
+
output_attentions (`bool`, *optional*):
|
| 853 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under
|
| 854 |
+
returned tensors for more detail.
|
| 855 |
+
output_hidden_states (`bool`, *optional*):
|
| 856 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors
|
| 857 |
+
for more detail.
|
| 858 |
+
return_dict (`bool`, *optional*):
|
| 859 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 860 |
+
"""
|
| 861 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 862 |
+
output_hidden_states = (
|
| 863 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 864 |
+
)
|
| 865 |
+
|
| 866 |
+
encoder_states = () if output_hidden_states else None
|
| 867 |
+
all_attentions = () if output_attentions else None
|
| 868 |
+
|
| 869 |
+
hidden_states = inputs_embeds
|
| 870 |
+
for idx, encoder_layer in enumerate(self.layers):
|
| 871 |
+
if output_hidden_states:
|
| 872 |
+
encoder_states = encoder_states + (hidden_states,)
|
| 873 |
+
if self.gradient_checkpointing and self.training:
|
| 874 |
+
layer_outputs = self._gradient_checkpointing_func(
|
| 875 |
+
encoder_layer.__call__,
|
| 876 |
+
hidden_states,
|
| 877 |
+
attention_mask,
|
| 878 |
+
causal_attention_mask,
|
| 879 |
+
output_attentions,
|
| 880 |
+
)
|
| 881 |
+
else:
|
| 882 |
+
layer_outputs = encoder_layer(
|
| 883 |
+
hidden_states,
|
| 884 |
+
attention_mask,
|
| 885 |
+
causal_attention_mask,
|
| 886 |
+
output_attentions=output_attentions,
|
| 887 |
+
)
|
| 888 |
+
|
| 889 |
+
hidden_states = layer_outputs[0]
|
| 890 |
+
|
| 891 |
+
if output_attentions:
|
| 892 |
+
all_attentions = all_attentions + (layer_outputs[1],)
|
| 893 |
+
|
| 894 |
+
if output_hidden_states:
|
| 895 |
+
encoder_states = encoder_states + (hidden_states,)
|
| 896 |
+
|
| 897 |
+
return BaseModelOutput(
|
| 898 |
+
last_hidden_state=hidden_states,
|
| 899 |
+
hidden_states=encoder_states,
|
| 900 |
+
attentions=all_attentions,
|
| 901 |
+
)
|
| 902 |
+
|
| 903 |
+
|
| 904 |
+
class CLIPTextTransformer(nn.Module):
|
| 905 |
+
def __init__(self, config: CLIPTextConfig):
|
| 906 |
+
super().__init__()
|
| 907 |
+
self.config = config
|
| 908 |
+
embed_dim = config.hidden_size
|
| 909 |
+
self.embeddings = CLIPTextEmbeddings(config)
|
| 910 |
+
self.encoder = CLIPEncoder(config)
|
| 911 |
+
self.final_layer_norm = nn.LayerNorm(embed_dim, eps=config.layer_norm_eps)
|
| 912 |
+
|
| 913 |
+
# For `pooled_output` computation
|
| 914 |
+
self.eos_token_id = config.eos_token_id
|
| 915 |
+
|
| 916 |
+
# For attention mask, it differs between `flash_attention_2` and other attention implementations
|
| 917 |
+
self._use_flash_attention_2 = config._attn_implementation == "flash_attention_2"
|
| 918 |
+
|
| 919 |
+
@can_return_tuple
|
| 920 |
+
@add_start_docstrings_to_model_forward(CLIP_TEXT_INPUTS_DOCSTRING)
|
| 921 |
+
@replace_return_docstrings(output_type=BaseModelOutputWithPooling, config_class=CLIPTextConfig)
|
| 922 |
+
def forward(
|
| 923 |
+
self,
|
| 924 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 925 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 926 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 927 |
+
output_attentions: Optional[bool] = None,
|
| 928 |
+
output_hidden_states: Optional[bool] = None,
|
| 929 |
+
) -> BaseModelOutputWithPooling:
|
| 930 |
+
r"""
|
| 931 |
+
Returns:
|
| 932 |
+
|
| 933 |
+
"""
|
| 934 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 935 |
+
output_hidden_states = (
|
| 936 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 937 |
+
)
|
| 938 |
+
|
| 939 |
+
if input_ids is None:
|
| 940 |
+
raise ValueError("You have to specify input_ids")
|
| 941 |
+
|
| 942 |
+
input_shape = input_ids.size()
|
| 943 |
+
input_ids = input_ids.view(-1, input_shape[-1])
|
| 944 |
+
|
| 945 |
+
hidden_states = self.embeddings(input_ids=input_ids, position_ids=position_ids)
|
| 946 |
+
|
| 947 |
+
# CLIP's text model uses causal mask, prepare it here.
|
| 948 |
+
# https://github.com/openai/CLIP/blob/cfcffb90e69f37bf2ff1e988237a0fbe41f33c04/clip/model.py#L324
|
| 949 |
+
causal_attention_mask = _create_4d_causal_attention_mask(
|
| 950 |
+
input_shape, hidden_states.dtype, device=hidden_states.device
|
| 951 |
+
)
|
| 952 |
+
|
| 953 |
+
# expand attention_mask
|
| 954 |
+
if attention_mask is not None and not self._use_flash_attention_2:
|
| 955 |
+
# [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len]
|
| 956 |
+
attention_mask = _prepare_4d_attention_mask(attention_mask, hidden_states.dtype)
|
| 957 |
+
|
| 958 |
+
encoder_outputs: BaseModelOutput = self.encoder(
|
| 959 |
+
inputs_embeds=hidden_states,
|
| 960 |
+
attention_mask=attention_mask,
|
| 961 |
+
causal_attention_mask=causal_attention_mask,
|
| 962 |
+
output_attentions=output_attentions,
|
| 963 |
+
output_hidden_states=output_hidden_states,
|
| 964 |
+
)
|
| 965 |
+
|
| 966 |
+
last_hidden_state = encoder_outputs.last_hidden_state
|
| 967 |
+
last_hidden_state = self.final_layer_norm(last_hidden_state)
|
| 968 |
+
|
| 969 |
+
if self.eos_token_id == 2:
|
| 970 |
+
# The `eos_token_id` was incorrect before PR #24773: Let's keep what have been done here.
|
| 971 |
+
# A CLIP model with such `eos_token_id` in the config can't work correctly with extra new tokens added
|
| 972 |
+
# ------------------------------------------------------------
|
| 973 |
+
# text_embeds.shape = [batch_size, sequence_length, transformer.width]
|
| 974 |
+
# take features from the eot embedding (eot_token is the highest number in each sequence)
|
| 975 |
+
# casting to torch.int for onnx compatibility: argmax doesn't support int64 inputs with opset 14
|
| 976 |
+
pooled_output = last_hidden_state[
|
| 977 |
+
torch.arange(last_hidden_state.shape[0], device=last_hidden_state.device),
|
| 978 |
+
input_ids.to(dtype=torch.int, device=last_hidden_state.device).argmax(dim=-1),
|
| 979 |
+
]
|
| 980 |
+
else:
|
| 981 |
+
# The config gets updated `eos_token_id` from PR #24773 (so the use of exta new tokens is possible)
|
| 982 |
+
pooled_output = last_hidden_state[
|
| 983 |
+
torch.arange(last_hidden_state.shape[0], device=last_hidden_state.device),
|
| 984 |
+
# We need to get the first position of `eos_token_id` value (`pad_token_ids` might equal to `eos_token_id`)
|
| 985 |
+
# Note: we assume each sequence (along batch dim.) contains an `eos_token_id` (e.g. prepared by the tokenizer)
|
| 986 |
+
(input_ids.to(dtype=torch.int, device=last_hidden_state.device) == self.eos_token_id)
|
| 987 |
+
.int()
|
| 988 |
+
.argmax(dim=-1),
|
| 989 |
+
]
|
| 990 |
+
|
| 991 |
+
return BaseModelOutputWithPooling(
|
| 992 |
+
last_hidden_state=last_hidden_state,
|
| 993 |
+
pooler_output=pooled_output,
|
| 994 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 995 |
+
attentions=encoder_outputs.attentions,
|
| 996 |
+
)
|
| 997 |
+
|
| 998 |
+
|
| 999 |
+
@add_start_docstrings(
|
| 1000 |
+
"""The text model from CLIP without any head or projection on top.""",
|
| 1001 |
+
CLIP_START_DOCSTRING,
|
| 1002 |
+
)
|
| 1003 |
+
class CLIPTextModel(CLIPPreTrainedModel):
|
| 1004 |
+
config_class = CLIPTextConfig
|
| 1005 |
+
|
| 1006 |
+
_no_split_modules = ["CLIPTextEmbeddings", "CLIPEncoderLayer"]
|
| 1007 |
+
|
| 1008 |
+
def __init__(self, config: CLIPTextConfig):
|
| 1009 |
+
super().__init__(config)
|
| 1010 |
+
self.text_model = CLIPTextTransformer(config)
|
| 1011 |
+
# Initialize weights and apply final processing
|
| 1012 |
+
self.post_init()
|
| 1013 |
+
|
| 1014 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 1015 |
+
return self.text_model.embeddings.token_embedding
|
| 1016 |
+
|
| 1017 |
+
def set_input_embeddings(self, value):
|
| 1018 |
+
self.text_model.embeddings.token_embedding = value
|
| 1019 |
+
|
| 1020 |
+
@can_return_tuple
|
| 1021 |
+
@add_start_docstrings_to_model_forward(CLIP_TEXT_INPUTS_DOCSTRING)
|
| 1022 |
+
@replace_return_docstrings(output_type=BaseModelOutputWithPooling, config_class=CLIPTextConfig)
|
| 1023 |
+
def forward(
|
| 1024 |
+
self,
|
| 1025 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 1026 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 1027 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 1028 |
+
output_attentions: Optional[bool] = None,
|
| 1029 |
+
output_hidden_states: Optional[bool] = None,
|
| 1030 |
+
) -> BaseModelOutputWithPooling:
|
| 1031 |
+
r"""
|
| 1032 |
+
Returns:
|
| 1033 |
+
|
| 1034 |
+
Examples:
|
| 1035 |
+
|
| 1036 |
+
```python
|
| 1037 |
+
>>> from transformers import AutoTokenizer, CLIPTextModel
|
| 1038 |
+
|
| 1039 |
+
>>> model = CLIPTextModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1040 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 1041 |
+
|
| 1042 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="pt")
|
| 1043 |
+
|
| 1044 |
+
>>> outputs = model(**inputs)
|
| 1045 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 1046 |
+
>>> pooled_output = outputs.pooler_output # pooled (EOS token) states
|
| 1047 |
+
```"""
|
| 1048 |
+
|
| 1049 |
+
return self.text_model(
|
| 1050 |
+
input_ids=input_ids,
|
| 1051 |
+
attention_mask=attention_mask,
|
| 1052 |
+
position_ids=position_ids,
|
| 1053 |
+
output_attentions=output_attentions,
|
| 1054 |
+
output_hidden_states=output_hidden_states,
|
| 1055 |
+
)
|
| 1056 |
+
|
| 1057 |
+
|
| 1058 |
+
class CLIPVisionTransformer(nn.Module):
|
| 1059 |
+
def __init__(self, config: CLIPVisionConfig):
|
| 1060 |
+
super().__init__()
|
| 1061 |
+
self.config = config
|
| 1062 |
+
embed_dim = config.hidden_size
|
| 1063 |
+
|
| 1064 |
+
self.embeddings = CLIPVisionEmbeddings(config)
|
| 1065 |
+
self.pre_layrnorm = nn.LayerNorm(embed_dim, eps=config.layer_norm_eps)
|
| 1066 |
+
self.encoder = CLIPEncoder(config)
|
| 1067 |
+
self.post_layernorm = nn.LayerNorm(embed_dim, eps=config.layer_norm_eps)
|
| 1068 |
+
|
| 1069 |
+
@can_return_tuple
|
| 1070 |
+
@add_start_docstrings_to_model_forward(CLIP_VISION_INPUTS_DOCSTRING)
|
| 1071 |
+
@replace_return_docstrings(output_type=BaseModelOutputWithPooling, config_class=CLIPVisionConfig)
|
| 1072 |
+
def forward(
|
| 1073 |
+
self,
|
| 1074 |
+
pixel_values: Optional[torch.FloatTensor] = None,
|
| 1075 |
+
output_attentions: Optional[bool] = None,
|
| 1076 |
+
output_hidden_states: Optional[bool] = None,
|
| 1077 |
+
interpolate_pos_encoding: Optional[bool] = False,
|
| 1078 |
+
) -> BaseModelOutputWithPooling:
|
| 1079 |
+
r"""
|
| 1080 |
+
Returns:
|
| 1081 |
+
|
| 1082 |
+
"""
|
| 1083 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 1084 |
+
output_hidden_states = (
|
| 1085 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 1086 |
+
)
|
| 1087 |
+
|
| 1088 |
+
if pixel_values is None:
|
| 1089 |
+
raise ValueError("You have to specify pixel_values")
|
| 1090 |
+
|
| 1091 |
+
hidden_states = self.embeddings(pixel_values, interpolate_pos_encoding=interpolate_pos_encoding)
|
| 1092 |
+
hidden_states = self.pre_layrnorm(hidden_states)
|
| 1093 |
+
|
| 1094 |
+
encoder_outputs: BaseModelOutput = self.encoder(
|
| 1095 |
+
inputs_embeds=hidden_states,
|
| 1096 |
+
output_attentions=output_attentions,
|
| 1097 |
+
output_hidden_states=output_hidden_states,
|
| 1098 |
+
)
|
| 1099 |
+
|
| 1100 |
+
last_hidden_state = encoder_outputs.last_hidden_state
|
| 1101 |
+
pooled_output = last_hidden_state[:, 0, :]
|
| 1102 |
+
pooled_output = self.post_layernorm(pooled_output)
|
| 1103 |
+
|
| 1104 |
+
return BaseModelOutputWithPooling(
|
| 1105 |
+
last_hidden_state=last_hidden_state,
|
| 1106 |
+
pooler_output=pooled_output,
|
| 1107 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 1108 |
+
attentions=encoder_outputs.attentions,
|
| 1109 |
+
)
|
| 1110 |
+
|
| 1111 |
+
|
| 1112 |
+
@add_start_docstrings(
|
| 1113 |
+
"""The vision model from CLIP without any head or projection on top.""",
|
| 1114 |
+
CLIP_START_DOCSTRING,
|
| 1115 |
+
)
|
| 1116 |
+
class CLIPVisionModel(CLIPPreTrainedModel):
|
| 1117 |
+
config_class = CLIPVisionConfig
|
| 1118 |
+
main_input_name = "pixel_values"
|
| 1119 |
+
_no_split_modules = ["CLIPEncoderLayer"]
|
| 1120 |
+
|
| 1121 |
+
def __init__(self, config: CLIPVisionConfig):
|
| 1122 |
+
super().__init__(config)
|
| 1123 |
+
self.vision_model = CLIPVisionTransformer(config)
|
| 1124 |
+
# Initialize weights and apply final processing
|
| 1125 |
+
self.post_init()
|
| 1126 |
+
|
| 1127 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 1128 |
+
return self.vision_model.embeddings.patch_embedding
|
| 1129 |
+
|
| 1130 |
+
@can_return_tuple
|
| 1131 |
+
@add_start_docstrings_to_model_forward(CLIP_VISION_INPUTS_DOCSTRING)
|
| 1132 |
+
@replace_return_docstrings(output_type=BaseModelOutputWithPooling, config_class=CLIPVisionConfig)
|
| 1133 |
+
def forward(
|
| 1134 |
+
self,
|
| 1135 |
+
pixel_values: Optional[torch.FloatTensor] = None,
|
| 1136 |
+
output_attentions: Optional[bool] = None,
|
| 1137 |
+
output_hidden_states: Optional[bool] = None,
|
| 1138 |
+
interpolate_pos_encoding: bool = False,
|
| 1139 |
+
) -> BaseModelOutputWithPooling:
|
| 1140 |
+
r"""
|
| 1141 |
+
Returns:
|
| 1142 |
+
|
| 1143 |
+
Examples:
|
| 1144 |
+
|
| 1145 |
+
```python
|
| 1146 |
+
>>> from PIL import Image
|
| 1147 |
+
>>> import requests
|
| 1148 |
+
>>> from transformers import AutoProcessor, CLIPVisionModel
|
| 1149 |
+
|
| 1150 |
+
>>> model = CLIPVisionModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1151 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1152 |
+
|
| 1153 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1154 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1155 |
+
|
| 1156 |
+
>>> inputs = processor(images=image, return_tensors="pt")
|
| 1157 |
+
|
| 1158 |
+
>>> outputs = model(**inputs)
|
| 1159 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 1160 |
+
>>> pooled_output = outputs.pooler_output # pooled CLS states
|
| 1161 |
+
```"""
|
| 1162 |
+
|
| 1163 |
+
return self.vision_model(
|
| 1164 |
+
pixel_values=pixel_values,
|
| 1165 |
+
output_attentions=output_attentions,
|
| 1166 |
+
output_hidden_states=output_hidden_states,
|
| 1167 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 1168 |
+
)
|
| 1169 |
+
|
| 1170 |
+
|
| 1171 |
+
@add_start_docstrings(CLIP_START_DOCSTRING)
|
| 1172 |
+
class CLIPModel(CLIPPreTrainedModel):
|
| 1173 |
+
config_class = CLIPConfig
|
| 1174 |
+
_no_split_modules = ["CLIPTextEmbeddings", "CLIPEncoderLayer", "CLIPVisionEmbeddings"]
|
| 1175 |
+
|
| 1176 |
+
def __init__(self, config: CLIPConfig):
|
| 1177 |
+
super().__init__(config)
|
| 1178 |
+
|
| 1179 |
+
if not isinstance(config.text_config, CLIPTextConfig):
|
| 1180 |
+
raise TypeError(
|
| 1181 |
+
"config.text_config is expected to be of type CLIPTextConfig but is of type"
|
| 1182 |
+
f" {type(config.text_config)}."
|
| 1183 |
+
)
|
| 1184 |
+
|
| 1185 |
+
if not isinstance(config.vision_config, CLIPVisionConfig):
|
| 1186 |
+
raise TypeError(
|
| 1187 |
+
"config.vision_config is expected to be of type CLIPVisionConfig but is of type"
|
| 1188 |
+
f" {type(config.vision_config)}."
|
| 1189 |
+
)
|
| 1190 |
+
|
| 1191 |
+
text_config = config.text_config
|
| 1192 |
+
vision_config = config.vision_config
|
| 1193 |
+
|
| 1194 |
+
self.projection_dim = config.projection_dim
|
| 1195 |
+
self.text_embed_dim = text_config.hidden_size
|
| 1196 |
+
self.vision_embed_dim = vision_config.hidden_size
|
| 1197 |
+
|
| 1198 |
+
text_model = CLIPTextModel._from_config(text_config)
|
| 1199 |
+
self.text_model = text_model.text_model
|
| 1200 |
+
|
| 1201 |
+
vision_model = CLIPVisionModel._from_config(vision_config)
|
| 1202 |
+
self.vision_model = vision_model.vision_model
|
| 1203 |
+
|
| 1204 |
+
self.visual_projection = nn.Linear(self.vision_embed_dim, self.projection_dim, bias=False)
|
| 1205 |
+
self.text_projection = nn.Linear(self.text_embed_dim, self.projection_dim, bias=False)
|
| 1206 |
+
self.logit_scale = nn.Parameter(torch.tensor(self.config.logit_scale_init_value))
|
| 1207 |
+
|
| 1208 |
+
# Initialize weights and apply final processing
|
| 1209 |
+
self.post_init()
|
| 1210 |
+
|
| 1211 |
+
@add_start_docstrings_to_model_forward(CLIP_TEXT_INPUTS_DOCSTRING)
|
| 1212 |
+
def get_text_features(
|
| 1213 |
+
self,
|
| 1214 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 1215 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 1216 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 1217 |
+
output_attentions: Optional[bool] = None,
|
| 1218 |
+
output_hidden_states: Optional[bool] = None,
|
| 1219 |
+
) -> torch.FloatTensor:
|
| 1220 |
+
r"""
|
| 1221 |
+
Returns:
|
| 1222 |
+
text_features (`torch.FloatTensor` of shape `(batch_size, output_dim`): The text embeddings obtained by
|
| 1223 |
+
applying the projection layer to the pooled output of [`CLIPTextModel`].
|
| 1224 |
+
|
| 1225 |
+
Examples:
|
| 1226 |
+
|
| 1227 |
+
```python
|
| 1228 |
+
>>> from transformers import AutoTokenizer, CLIPModel
|
| 1229 |
+
|
| 1230 |
+
>>> model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1231 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 1232 |
+
|
| 1233 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="pt")
|
| 1234 |
+
>>> text_features = model.get_text_features(**inputs)
|
| 1235 |
+
```"""
|
| 1236 |
+
# Use CLIP model's config for some fields (if specified) instead of those of vision & text components.
|
| 1237 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 1238 |
+
output_hidden_states = (
|
| 1239 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 1240 |
+
)
|
| 1241 |
+
|
| 1242 |
+
text_outputs: BaseModelOutputWithPooling = self.text_model(
|
| 1243 |
+
input_ids=input_ids,
|
| 1244 |
+
attention_mask=attention_mask,
|
| 1245 |
+
position_ids=position_ids,
|
| 1246 |
+
output_attentions=output_attentions,
|
| 1247 |
+
output_hidden_states=output_hidden_states,
|
| 1248 |
+
)
|
| 1249 |
+
|
| 1250 |
+
pooled_output = text_outputs.pooler_output
|
| 1251 |
+
text_features = self.text_projection(pooled_output)
|
| 1252 |
+
|
| 1253 |
+
return text_features
|
| 1254 |
+
|
| 1255 |
+
@add_start_docstrings_to_model_forward(CLIP_VISION_INPUTS_DOCSTRING)
|
| 1256 |
+
def get_image_features(
|
| 1257 |
+
self,
|
| 1258 |
+
pixel_values: Optional[torch.FloatTensor] = None,
|
| 1259 |
+
output_attentions: Optional[bool] = None,
|
| 1260 |
+
output_hidden_states: Optional[bool] = None,
|
| 1261 |
+
interpolate_pos_encoding: bool = False,
|
| 1262 |
+
) -> torch.FloatTensor:
|
| 1263 |
+
r"""
|
| 1264 |
+
Returns:
|
| 1265 |
+
image_features (`torch.FloatTensor` of shape `(batch_size, output_dim`): The image embeddings obtained by
|
| 1266 |
+
applying the projection layer to the pooled output of [`CLIPVisionModel`].
|
| 1267 |
+
|
| 1268 |
+
Examples:
|
| 1269 |
+
|
| 1270 |
+
```python
|
| 1271 |
+
>>> from PIL import Image
|
| 1272 |
+
>>> import requests
|
| 1273 |
+
>>> from transformers import AutoProcessor, CLIPModel
|
| 1274 |
+
|
| 1275 |
+
>>> model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1276 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1277 |
+
|
| 1278 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1279 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1280 |
+
|
| 1281 |
+
>>> inputs = processor(images=image, return_tensors="pt")
|
| 1282 |
+
|
| 1283 |
+
>>> image_features = model.get_image_features(**inputs)
|
| 1284 |
+
```"""
|
| 1285 |
+
# Use CLIP model's config for some fields (if specified) instead of those of vision & text components.
|
| 1286 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 1287 |
+
output_hidden_states = (
|
| 1288 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 1289 |
+
)
|
| 1290 |
+
|
| 1291 |
+
vision_outputs: BaseModelOutputWithPooling = self.vision_model(
|
| 1292 |
+
pixel_values=pixel_values,
|
| 1293 |
+
output_attentions=output_attentions,
|
| 1294 |
+
output_hidden_states=output_hidden_states,
|
| 1295 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 1296 |
+
)
|
| 1297 |
+
|
| 1298 |
+
pooled_output = vision_outputs.pooler_output
|
| 1299 |
+
image_features = self.visual_projection(pooled_output)
|
| 1300 |
+
|
| 1301 |
+
return image_features
|
| 1302 |
+
|
| 1303 |
+
@can_return_tuple
|
| 1304 |
+
@add_start_docstrings_to_model_forward(CLIP_INPUTS_DOCSTRING)
|
| 1305 |
+
@replace_return_docstrings(output_type=CLIPOutput, config_class=CLIPConfig)
|
| 1306 |
+
def forward(
|
| 1307 |
+
self,
|
| 1308 |
+
input_ids: Optional[torch.LongTensor] = None,
|
| 1309 |
+
pixel_values: Optional[torch.FloatTensor] = None,
|
| 1310 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 1311 |
+
position_ids: Optional[torch.LongTensor] = None,
|
| 1312 |
+
return_loss: Optional[bool] = None,
|
| 1313 |
+
output_attentions: Optional[bool] = None,
|
| 1314 |
+
output_hidden_states: Optional[bool] = None,
|
| 1315 |
+
interpolate_pos_encoding: bool = False,
|
| 1316 |
+
) -> CLIPOutput:
|
| 1317 |
+
r"""
|
| 1318 |
+
Returns:
|
| 1319 |
+
|
| 1320 |
+
Examples:
|
| 1321 |
+
|
| 1322 |
+
```python
|
| 1323 |
+
>>> from PIL import Image
|
| 1324 |
+
>>> import requests
|
| 1325 |
+
>>> from transformers import AutoProcessor, CLIPModel
|
| 1326 |
+
|
| 1327 |
+
>>> model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1328 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1329 |
+
|
| 1330 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1331 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1332 |
+
|
| 1333 |
+
>>> inputs = processor(
|
| 1334 |
+
... text=["a photo of a cat", "a photo of a dog"], images=image, return_tensors="pt", padding=True
|
| 1335 |
+
... )
|
| 1336 |
+
|
| 1337 |
+
>>> outputs = model(**inputs)
|
| 1338 |
+
>>> logits_per_image = outputs.logits_per_image # this is the image-text similarity score
|
| 1339 |
+
>>> probs = logits_per_image.softmax(dim=1) # we can take the softmax to get the label probabilities
|
| 1340 |
+
```"""
|
| 1341 |
+
# Use CLIP model's config for some fields (if specified) instead of those of vision & text components.
|
| 1342 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 1343 |
+
output_hidden_states = (
|
| 1344 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 1345 |
+
)
|
| 1346 |
+
|
| 1347 |
+
vision_outputs: BaseModelOutputWithPooling = self.vision_model(
|
| 1348 |
+
pixel_values=pixel_values,
|
| 1349 |
+
output_attentions=output_attentions,
|
| 1350 |
+
output_hidden_states=output_hidden_states,
|
| 1351 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 1352 |
+
)
|
| 1353 |
+
|
| 1354 |
+
text_outputs: BaseModelOutputWithPooling = self.text_model(
|
| 1355 |
+
input_ids=input_ids,
|
| 1356 |
+
attention_mask=attention_mask,
|
| 1357 |
+
position_ids=position_ids,
|
| 1358 |
+
output_attentions=output_attentions,
|
| 1359 |
+
output_hidden_states=output_hidden_states,
|
| 1360 |
+
)
|
| 1361 |
+
|
| 1362 |
+
image_embeds = vision_outputs.pooler_output
|
| 1363 |
+
image_embeds = self.visual_projection(image_embeds)
|
| 1364 |
+
|
| 1365 |
+
text_embeds = text_outputs.pooler_output
|
| 1366 |
+
text_embeds = self.text_projection(text_embeds)
|
| 1367 |
+
|
| 1368 |
+
# normalized features
|
| 1369 |
+
image_embeds = image_embeds / _get_vector_norm(image_embeds)
|
| 1370 |
+
text_embeds = text_embeds / _get_vector_norm(text_embeds)
|
| 1371 |
+
|
| 1372 |
+
# cosine similarity as logits
|
| 1373 |
+
logits_per_text = torch.matmul(text_embeds, image_embeds.t().to(text_embeds.device))
|
| 1374 |
+
logits_per_text = logits_per_text * self.logit_scale.exp().to(text_embeds.device)
|
| 1375 |
+
|
| 1376 |
+
logits_per_image = logits_per_text.t()
|
| 1377 |
+
|
| 1378 |
+
loss = None
|
| 1379 |
+
if return_loss:
|
| 1380 |
+
loss = clip_loss(logits_per_text)
|
| 1381 |
+
|
| 1382 |
+
return CLIPOutput(
|
| 1383 |
+
loss=loss,
|
| 1384 |
+
logits_per_image=logits_per_image,
|
| 1385 |
+
logits_per_text=logits_per_text,
|
| 1386 |
+
text_embeds=text_embeds,
|
| 1387 |
+
image_embeds=image_embeds,
|
| 1388 |
+
text_model_output=text_outputs,
|
| 1389 |
+
vision_model_output=vision_outputs,
|
| 1390 |
+
)
|
| 1391 |
+
|
| 1392 |
+
|
| 1393 |
+
@add_start_docstrings(
|
| 1394 |
+
"""
|
| 1395 |
+
CLIP Text Model with a projection layer on top (a linear layer on top of the pooled output).
|
| 1396 |
+
""",
|
| 1397 |
+
CLIP_START_DOCSTRING,
|
| 1398 |
+
)
|
| 1399 |
+
class CLIPTextModelWithProjection(CLIPPreTrainedModel):
|
| 1400 |
+
config_class = CLIPTextConfig
|
| 1401 |
+
|
| 1402 |
+
_no_split_modules = ["CLIPTextEmbeddings", "CLIPEncoderLayer"]
|
| 1403 |
+
|
| 1404 |
+
def __init__(self, config: CLIPTextConfig):
|
| 1405 |
+
super().__init__(config)
|
| 1406 |
+
|
| 1407 |
+
text_model = CLIPTextModel._from_config(config)
|
| 1408 |
+
self.text_model = text_model.text_model
|
| 1409 |
+
|
| 1410 |
+
self.text_projection = nn.Linear(config.hidden_size, config.projection_dim, bias=False)
|
| 1411 |
+
|
| 1412 |
+
# Initialize weights and apply final processing
|
| 1413 |
+
self.post_init()
|
| 1414 |
+
|
| 1415 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 1416 |
+
return self.text_model.embeddings.token_embedding
|
| 1417 |
+
|
| 1418 |
+
def set_input_embeddings(self, value):
|
| 1419 |
+
self.text_model.embeddings.token_embedding = value
|
| 1420 |
+
|
| 1421 |
+
@can_return_tuple
|
| 1422 |
+
@add_start_docstrings_to_model_forward(CLIP_TEXT_INPUTS_DOCSTRING)
|
| 1423 |
+
@replace_return_docstrings(output_type=CLIPTextModelOutput, config_class=CLIPTextConfig)
|
| 1424 |
+
def forward(
|
| 1425 |
+
self,
|
| 1426 |
+
input_ids: Optional[torch.Tensor] = None,
|
| 1427 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 1428 |
+
position_ids: Optional[torch.Tensor] = None,
|
| 1429 |
+
output_attentions: Optional[bool] = None,
|
| 1430 |
+
output_hidden_states: Optional[bool] = None,
|
| 1431 |
+
) -> CLIPTextModelOutput:
|
| 1432 |
+
r"""
|
| 1433 |
+
Returns:
|
| 1434 |
+
|
| 1435 |
+
Examples:
|
| 1436 |
+
|
| 1437 |
+
```python
|
| 1438 |
+
>>> from transformers import AutoTokenizer, CLIPTextModelWithProjection
|
| 1439 |
+
|
| 1440 |
+
>>> model = CLIPTextModelWithProjection.from_pretrained("openai/clip-vit-base-patch32")
|
| 1441 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 1442 |
+
|
| 1443 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="pt")
|
| 1444 |
+
|
| 1445 |
+
>>> outputs = model(**inputs)
|
| 1446 |
+
>>> text_embeds = outputs.text_embeds
|
| 1447 |
+
```"""
|
| 1448 |
+
|
| 1449 |
+
text_outputs: BaseModelOutputWithPooling = self.text_model(
|
| 1450 |
+
input_ids=input_ids,
|
| 1451 |
+
attention_mask=attention_mask,
|
| 1452 |
+
position_ids=position_ids,
|
| 1453 |
+
output_attentions=output_attentions,
|
| 1454 |
+
output_hidden_states=output_hidden_states,
|
| 1455 |
+
)
|
| 1456 |
+
pooled_output = text_outputs.pooler_output
|
| 1457 |
+
text_embeds = self.text_projection(pooled_output)
|
| 1458 |
+
|
| 1459 |
+
return CLIPTextModelOutput(
|
| 1460 |
+
text_embeds=text_embeds,
|
| 1461 |
+
last_hidden_state=text_outputs.last_hidden_state,
|
| 1462 |
+
hidden_states=text_outputs.hidden_states,
|
| 1463 |
+
attentions=text_outputs.attentions,
|
| 1464 |
+
)
|
| 1465 |
+
|
| 1466 |
+
|
| 1467 |
+
@add_start_docstrings(
|
| 1468 |
+
"""
|
| 1469 |
+
CLIP Vision Model with a projection layer on top (a linear layer on top of the pooled output).
|
| 1470 |
+
""",
|
| 1471 |
+
CLIP_START_DOCSTRING,
|
| 1472 |
+
)
|
| 1473 |
+
class CLIPVisionModelWithProjection(CLIPPreTrainedModel):
|
| 1474 |
+
config_class = CLIPVisionConfig
|
| 1475 |
+
main_input_name = "pixel_values"
|
| 1476 |
+
|
| 1477 |
+
def __init__(self, config: CLIPVisionConfig):
|
| 1478 |
+
super().__init__(config)
|
| 1479 |
+
|
| 1480 |
+
vision_model = CLIPVisionModel._from_config(config)
|
| 1481 |
+
self.vision_model = vision_model.vision_model
|
| 1482 |
+
|
| 1483 |
+
self.visual_projection = nn.Linear(config.hidden_size, config.projection_dim, bias=False)
|
| 1484 |
+
|
| 1485 |
+
# Initialize weights and apply final processing
|
| 1486 |
+
self.post_init()
|
| 1487 |
+
|
| 1488 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 1489 |
+
return self.vision_model.embeddings.patch_embedding
|
| 1490 |
+
|
| 1491 |
+
@can_return_tuple
|
| 1492 |
+
@add_start_docstrings_to_model_forward(CLIP_VISION_INPUTS_DOCSTRING)
|
| 1493 |
+
@replace_return_docstrings(output_type=CLIPVisionModelOutput, config_class=CLIPVisionConfig)
|
| 1494 |
+
def forward(
|
| 1495 |
+
self,
|
| 1496 |
+
pixel_values: Optional[torch.FloatTensor] = None,
|
| 1497 |
+
output_attentions: Optional[bool] = None,
|
| 1498 |
+
output_hidden_states: Optional[bool] = None,
|
| 1499 |
+
interpolate_pos_encoding: bool = False,
|
| 1500 |
+
) -> CLIPVisionModelOutput:
|
| 1501 |
+
r"""
|
| 1502 |
+
Returns:
|
| 1503 |
+
|
| 1504 |
+
Examples:
|
| 1505 |
+
|
| 1506 |
+
```python
|
| 1507 |
+
>>> from PIL import Image
|
| 1508 |
+
>>> import requests
|
| 1509 |
+
>>> from transformers import AutoProcessor, CLIPVisionModelWithProjection
|
| 1510 |
+
|
| 1511 |
+
>>> model = CLIPVisionModelWithProjection.from_pretrained("openai/clip-vit-base-patch32")
|
| 1512 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1513 |
+
|
| 1514 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1515 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1516 |
+
|
| 1517 |
+
>>> inputs = processor(images=image, return_tensors="pt")
|
| 1518 |
+
|
| 1519 |
+
>>> outputs = model(**inputs)
|
| 1520 |
+
>>> image_embeds = outputs.image_embeds
|
| 1521 |
+
```"""
|
| 1522 |
+
|
| 1523 |
+
vision_outputs: BaseModelOutputWithPooling = self.vision_model(
|
| 1524 |
+
pixel_values=pixel_values,
|
| 1525 |
+
output_attentions=output_attentions,
|
| 1526 |
+
output_hidden_states=output_hidden_states,
|
| 1527 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 1528 |
+
)
|
| 1529 |
+
pooled_output = vision_outputs.pooler_output
|
| 1530 |
+
image_embeds = self.visual_projection(pooled_output)
|
| 1531 |
+
|
| 1532 |
+
return CLIPVisionModelOutput(
|
| 1533 |
+
image_embeds=image_embeds,
|
| 1534 |
+
last_hidden_state=vision_outputs.last_hidden_state,
|
| 1535 |
+
hidden_states=vision_outputs.hidden_states,
|
| 1536 |
+
attentions=vision_outputs.attentions,
|
| 1537 |
+
)
|
| 1538 |
+
|
| 1539 |
+
|
| 1540 |
+
@add_start_docstrings(
|
| 1541 |
+
"""
|
| 1542 |
+
CLIP vision encoder with an image classification head on top (a linear layer on top of the pooled final hidden states of
|
| 1543 |
+
the patch tokens) e.g. for ImageNet.
|
| 1544 |
+
""",
|
| 1545 |
+
CLIP_START_DOCSTRING,
|
| 1546 |
+
)
|
| 1547 |
+
class CLIPForImageClassification(CLIPPreTrainedModel):
|
| 1548 |
+
main_input_name = "pixel_values"
|
| 1549 |
+
|
| 1550 |
+
def __init__(self, config: CLIPConfig) -> None:
|
| 1551 |
+
super().__init__(config)
|
| 1552 |
+
|
| 1553 |
+
self.num_labels = config.num_labels
|
| 1554 |
+
vision_model = CLIPVisionModel._from_config(config.vision_config)
|
| 1555 |
+
self.vision_model = vision_model.vision_model
|
| 1556 |
+
|
| 1557 |
+
# Classifier head
|
| 1558 |
+
self.classifier = (
|
| 1559 |
+
nn.Linear(config.vision_config.hidden_size, config.num_labels) if config.num_labels > 0 else nn.Identity()
|
| 1560 |
+
)
|
| 1561 |
+
|
| 1562 |
+
# Initialize weights and apply final processing
|
| 1563 |
+
self.post_init()
|
| 1564 |
+
|
| 1565 |
+
@can_return_tuple
|
| 1566 |
+
@add_start_docstrings_to_model_forward(CLIP_INPUTS_DOCSTRING)
|
| 1567 |
+
@add_code_sample_docstrings(
|
| 1568 |
+
checkpoint=_IMAGE_CLASS_CHECKPOINT,
|
| 1569 |
+
output_type=ImageClassifierOutput,
|
| 1570 |
+
config_class=_CONFIG_FOR_DOC,
|
| 1571 |
+
expected_output=_IMAGE_CLASS_EXPECTED_OUTPUT,
|
| 1572 |
+
)
|
| 1573 |
+
def forward(
|
| 1574 |
+
self,
|
| 1575 |
+
pixel_values: Optional[torch.Tensor] = None,
|
| 1576 |
+
labels: Optional[torch.Tensor] = None,
|
| 1577 |
+
output_attentions: Optional[bool] = None,
|
| 1578 |
+
output_hidden_states: Optional[bool] = None,
|
| 1579 |
+
) -> ImageClassifierOutput:
|
| 1580 |
+
r"""
|
| 1581 |
+
labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
|
| 1582 |
+
Labels for computing the image classification/regression loss. Indices should be in `[0, ...,
|
| 1583 |
+
config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
|
| 1584 |
+
`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
| 1585 |
+
"""
|
| 1586 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 1587 |
+
output_hidden_states = (
|
| 1588 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 1589 |
+
)
|
| 1590 |
+
|
| 1591 |
+
outputs: BaseModelOutputWithPooling = self.vision_model(
|
| 1592 |
+
pixel_values,
|
| 1593 |
+
output_attentions=output_attentions,
|
| 1594 |
+
output_hidden_states=output_hidden_states,
|
| 1595 |
+
)
|
| 1596 |
+
|
| 1597 |
+
sequence_output = outputs.last_hidden_state
|
| 1598 |
+
|
| 1599 |
+
# average pool the patch tokens
|
| 1600 |
+
sequence_output = torch.mean(sequence_output[:, 1:, :], dim=1)
|
| 1601 |
+
# apply classifier
|
| 1602 |
+
logits = self.classifier(sequence_output)
|
| 1603 |
+
|
| 1604 |
+
loss = None
|
| 1605 |
+
if labels is not None:
|
| 1606 |
+
# move labels to correct device to enable model parallelism
|
| 1607 |
+
labels = labels.to(logits.device)
|
| 1608 |
+
if self.config.problem_type is None:
|
| 1609 |
+
if self.num_labels == 1:
|
| 1610 |
+
self.config.problem_type = "regression"
|
| 1611 |
+
elif self.num_labels > 1 and (labels.dtype == torch.long or labels.dtype == torch.int):
|
| 1612 |
+
self.config.problem_type = "single_label_classification"
|
| 1613 |
+
else:
|
| 1614 |
+
self.config.problem_type = "multi_label_classification"
|
| 1615 |
+
|
| 1616 |
+
if self.config.problem_type == "regression":
|
| 1617 |
+
loss_fct = MSELoss()
|
| 1618 |
+
if self.num_labels == 1:
|
| 1619 |
+
loss = loss_fct(logits.squeeze(), labels.squeeze())
|
| 1620 |
+
else:
|
| 1621 |
+
loss = loss_fct(logits, labels)
|
| 1622 |
+
elif self.config.problem_type == "single_label_classification":
|
| 1623 |
+
loss_fct = CrossEntropyLoss()
|
| 1624 |
+
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
|
| 1625 |
+
elif self.config.problem_type == "multi_label_classification":
|
| 1626 |
+
loss_fct = BCEWithLogitsLoss()
|
| 1627 |
+
loss = loss_fct(logits, labels)
|
| 1628 |
+
|
| 1629 |
+
return ImageClassifierOutput(
|
| 1630 |
+
loss=loss,
|
| 1631 |
+
logits=logits,
|
| 1632 |
+
hidden_states=outputs.hidden_states,
|
| 1633 |
+
attentions=outputs.attentions,
|
| 1634 |
+
)
|
| 1635 |
+
|
| 1636 |
+
|
| 1637 |
+
__all__ = [
|
| 1638 |
+
"CLIPModel",
|
| 1639 |
+
"CLIPPreTrainedModel",
|
| 1640 |
+
"CLIPTextModel",
|
| 1641 |
+
"CLIPTextModelWithProjection",
|
| 1642 |
+
"CLIPVisionModel",
|
| 1643 |
+
"CLIPVisionModelWithProjection",
|
| 1644 |
+
"CLIPForImageClassification",
|
| 1645 |
+
]
|
lib/python3.12/site-packages/transformers/models/clip/modeling_flax_clip.py
ADDED
|
@@ -0,0 +1,1306 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2021 The OpenAI Team Authors, The Google Flax Team Authors and The HuggingFace Inc. team.
|
| 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 |
+
|
| 16 |
+
from typing import Any, Optional, Tuple, Union
|
| 17 |
+
|
| 18 |
+
import flax
|
| 19 |
+
import flax.linen as nn
|
| 20 |
+
import jax
|
| 21 |
+
import jax.numpy as jnp
|
| 22 |
+
from flax.core.frozen_dict import FrozenDict, freeze, unfreeze
|
| 23 |
+
from flax.linen import combine_masks, make_causal_mask
|
| 24 |
+
from flax.linen.attention import dot_product_attention_weights
|
| 25 |
+
from flax.traverse_util import flatten_dict, unflatten_dict
|
| 26 |
+
from jax import lax
|
| 27 |
+
|
| 28 |
+
from ...modeling_flax_outputs import FlaxBaseModelOutput, FlaxBaseModelOutputWithPooling
|
| 29 |
+
from ...modeling_flax_utils import (
|
| 30 |
+
ACT2FN,
|
| 31 |
+
FlaxPreTrainedModel,
|
| 32 |
+
append_replace_return_docstrings,
|
| 33 |
+
overwrite_call_docstring,
|
| 34 |
+
)
|
| 35 |
+
from ...utils import ModelOutput, add_start_docstrings, logging
|
| 36 |
+
from .configuration_clip import CLIPConfig, CLIPTextConfig, CLIPVisionConfig
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
logger = logging.get_logger(__name__)
|
| 40 |
+
|
| 41 |
+
CLIP_START_DOCSTRING = r"""
|
| 42 |
+
|
| 43 |
+
This model inherits from [`FlaxPreTrainedModel`]. Check the superclass documentation for the generic methods the
|
| 44 |
+
library implements for all its model (such as downloading, saving and converting weights from PyTorch models)
|
| 45 |
+
|
| 46 |
+
This model is also a
|
| 47 |
+
[flax.linen.Module](https://flax.readthedocs.io/en/latest/api_reference/flax.linen/module.html) subclass. Use it as
|
| 48 |
+
a regular Flax linen Module and refer to the Flax documentation for all matter related to general usage and
|
| 49 |
+
behavior.
|
| 50 |
+
|
| 51 |
+
Finally, this model supports inherent JAX features such as:
|
| 52 |
+
|
| 53 |
+
- [Just-In-Time (JIT) compilation](https://jax.readthedocs.io/en/latest/jax.html#just-in-time-compilation-jit)
|
| 54 |
+
- [Automatic Differentiation](https://jax.readthedocs.io/en/latest/jax.html#automatic-differentiation)
|
| 55 |
+
- [Vectorization](https://jax.readthedocs.io/en/latest/jax.html#vectorization-vmap)
|
| 56 |
+
- [Parallelization](https://jax.readthedocs.io/en/latest/jax.html#parallelization-pmap)
|
| 57 |
+
|
| 58 |
+
Parameters:
|
| 59 |
+
config ([`CLIPConfig`]): Model configuration class with all the parameters of the model.
|
| 60 |
+
Initializing with a config file does not load the weights associated with the model, only the
|
| 61 |
+
configuration. Check out the [`~FlaxPreTrainedModel.from_pretrained`] method to load the model weights.
|
| 62 |
+
dtype (`jax.numpy.dtype`, *optional*, defaults to `jax.numpy.float32`):
|
| 63 |
+
The data type of the computation. Can be one of `jax.numpy.float32`, `jax.numpy.float16` (on GPUs) and
|
| 64 |
+
`jax.numpy.bfloat16` (on TPUs).
|
| 65 |
+
|
| 66 |
+
This can be used to enable mixed-precision training or half-precision inference on GPUs or TPUs. If
|
| 67 |
+
specified all the computation will be performed with the given `dtype`.
|
| 68 |
+
|
| 69 |
+
**Note that this only specifies the dtype of the computation and does not influence the dtype of model
|
| 70 |
+
parameters.**
|
| 71 |
+
|
| 72 |
+
If you wish to change the dtype of the model parameters, see [`~FlaxPreTrainedModel.to_fp16`] and
|
| 73 |
+
[`~FlaxPreTrainedModel.to_bf16`].
|
| 74 |
+
"""
|
| 75 |
+
|
| 76 |
+
CLIP_TEXT_INPUTS_DOCSTRING = r"""
|
| 77 |
+
Args:
|
| 78 |
+
input_ids (`numpy.ndarray` of shape `(batch_size, sequence_length)`):
|
| 79 |
+
Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
|
| 80 |
+
it.
|
| 81 |
+
|
| 82 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 83 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 84 |
+
|
| 85 |
+
[What are input IDs?](../glossary#input-ids)
|
| 86 |
+
attention_mask (`numpy.ndarray` of shape `(batch_size, sequence_length)`, *optional*):
|
| 87 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 88 |
+
|
| 89 |
+
- 1 for tokens that are **not masked**,
|
| 90 |
+
- 0 for tokens that are **masked**.
|
| 91 |
+
|
| 92 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 93 |
+
position_ids (`numpy.ndarray` of shape `(batch_size, sequence_length)`, *optional*):
|
| 94 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 95 |
+
config.max_position_embeddings - 1]`.
|
| 96 |
+
|
| 97 |
+
[What are position IDs?](../glossary#position-ids)
|
| 98 |
+
output_attentions (`bool`, *optional*):
|
| 99 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 100 |
+
tensors for more detail.
|
| 101 |
+
output_hidden_states (`bool`, *optional*):
|
| 102 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 103 |
+
more detail.
|
| 104 |
+
return_dict (`bool`, *optional*):
|
| 105 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 106 |
+
"""
|
| 107 |
+
|
| 108 |
+
CLIP_VISION_INPUTS_DOCSTRING = r"""
|
| 109 |
+
Args:
|
| 110 |
+
pixel_values (`numpy.ndarray` of shape `(batch_size, num_channels, height, width)`):
|
| 111 |
+
Pixel values. Padding will be ignored by default should you provide it. Pixel values can be obtained using
|
| 112 |
+
[`AutoImageProcessor`]. See [`CLIPImageProcessor.__call__`] for details.
|
| 113 |
+
output_attentions (`bool`, *optional*):
|
| 114 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 115 |
+
tensors for more detail.
|
| 116 |
+
output_hidden_states (`bool`, *optional*):
|
| 117 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 118 |
+
more detail.
|
| 119 |
+
return_dict (`bool`, *optional*):
|
| 120 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 121 |
+
"""
|
| 122 |
+
|
| 123 |
+
CLIP_INPUTS_DOCSTRING = r"""
|
| 124 |
+
Args:
|
| 125 |
+
input_ids (`numpy.ndarray` of shape `(batch_size, sequence_length)`):
|
| 126 |
+
Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
|
| 127 |
+
it.
|
| 128 |
+
|
| 129 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 130 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 131 |
+
|
| 132 |
+
[What are input IDs?](../glossary#input-ids)
|
| 133 |
+
attention_mask (`numpy.ndarray` of shape `(batch_size, sequence_length)`, *optional*):
|
| 134 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 135 |
+
|
| 136 |
+
- 1 for tokens that are **not masked**,
|
| 137 |
+
- 0 for tokens that are **masked**.
|
| 138 |
+
|
| 139 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 140 |
+
position_ids (`numpy.ndarray` of shape `(batch_size, sequence_length)`, *optional*):
|
| 141 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 142 |
+
config.max_position_embeddings - 1]`.
|
| 143 |
+
|
| 144 |
+
[What are position IDs?](../glossary#position-ids)
|
| 145 |
+
pixel_values (`numpy.ndarray` of shape `(batch_size, num_channels, height, width)`):
|
| 146 |
+
Pixel values. Padding will be ignored by default should you provide it. Pixel values can be obtained using
|
| 147 |
+
[`AutoImageProcessor`]. See [`CLIPImageProcessor.__call__`] for details.
|
| 148 |
+
output_attentions (`bool`, *optional*):
|
| 149 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 150 |
+
tensors for more detail.
|
| 151 |
+
output_hidden_states (`bool`, *optional*):
|
| 152 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 153 |
+
more detail.
|
| 154 |
+
return_dict (`bool`, *optional*):
|
| 155 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 156 |
+
"""
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
@flax.struct.dataclass
|
| 160 |
+
class FlaxCLIPTextModelOutput(ModelOutput):
|
| 161 |
+
"""
|
| 162 |
+
Base class for text model's outputs that also contains a pooling of the last hidden states.
|
| 163 |
+
|
| 164 |
+
Args:
|
| 165 |
+
text_embeds (`jnp.ndarray` of shape `(batch_size, output_dim`):
|
| 166 |
+
The text embeddings obtained by applying the projection layer to the pooled output of
|
| 167 |
+
[`FlaxCLIPTextModel`].
|
| 168 |
+
last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 169 |
+
Sequence of hidden-states at the output of the last layer of the model.
|
| 170 |
+
hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
|
| 171 |
+
Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
|
| 172 |
+
`(batch_size, sequence_length, hidden_size)`.
|
| 173 |
+
|
| 174 |
+
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
| 175 |
+
attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
|
| 176 |
+
Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 177 |
+
sequence_length)`.
|
| 178 |
+
|
| 179 |
+
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
| 180 |
+
heads.
|
| 181 |
+
"""
|
| 182 |
+
|
| 183 |
+
text_embeds: jnp.ndarray = None
|
| 184 |
+
last_hidden_state: jnp.ndarray = None
|
| 185 |
+
hidden_states: Optional[Tuple[jnp.ndarray, ...]] = None
|
| 186 |
+
attentions: Optional[Tuple[jnp.ndarray, ...]] = None
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
@flax.struct.dataclass
|
| 190 |
+
class FlaxCLIPOutput(ModelOutput):
|
| 191 |
+
"""
|
| 192 |
+
Args:
|
| 193 |
+
logits_per_image:(`jnp.ndarray` of shape `(image_batch_size, text_batch_size)`):
|
| 194 |
+
The scaled dot product scores between `image_embeds` and `text_embeds`. This represents the image-text
|
| 195 |
+
similarity scores.
|
| 196 |
+
logits_per_text:(`jnp.ndarray` of shape `(text_batch_size, image_batch_size)`):
|
| 197 |
+
The scaled dot product scores between `text_embeds` and `image_embeds`. This represents the text-image
|
| 198 |
+
similarity scores.
|
| 199 |
+
text_embeds(`jnp.ndarray` of shape `(batch_size, output_dim`):
|
| 200 |
+
The text embeddings obtained by applying the projection layer to the pooled output of
|
| 201 |
+
[`FlaxCLIPTextModel`].
|
| 202 |
+
image_embeds(`jnp.ndarray` of shape `(batch_size, output_dim`):
|
| 203 |
+
The image embeddings obtained by applying the projection layer to the pooled output of
|
| 204 |
+
[`FlaxCLIPVisionModel`].
|
| 205 |
+
text_model_output(`FlaxBaseModelOutputWithPooling`):
|
| 206 |
+
The output of the [`FlaxCLIPTextModel`].
|
| 207 |
+
vision_model_output(`FlaxBaseModelOutputWithPooling`):
|
| 208 |
+
The output of the [`FlaxCLIPVisionModel`].
|
| 209 |
+
"""
|
| 210 |
+
|
| 211 |
+
logits_per_image: jnp.ndarray = None
|
| 212 |
+
logits_per_text: jnp.ndarray = None
|
| 213 |
+
text_embeds: jnp.ndarray = None
|
| 214 |
+
image_embeds: jnp.ndarray = None
|
| 215 |
+
text_model_output: FlaxBaseModelOutputWithPooling = None
|
| 216 |
+
vision_model_output: FlaxBaseModelOutputWithPooling = None
|
| 217 |
+
|
| 218 |
+
def to_tuple(self) -> Tuple[Any]:
|
| 219 |
+
return tuple(
|
| 220 |
+
self[k] if k not in ["text_model_output", "vision_model_output"] else getattr(self, k).to_tuple()
|
| 221 |
+
for k in self.keys()
|
| 222 |
+
)
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
class FlaxCLIPVisionEmbeddings(nn.Module):
|
| 226 |
+
config: CLIPVisionConfig
|
| 227 |
+
dtype: jnp.dtype = jnp.float32
|
| 228 |
+
|
| 229 |
+
def setup(self):
|
| 230 |
+
embed_dim = self.config.hidden_size
|
| 231 |
+
image_size = self.config.image_size
|
| 232 |
+
patch_size = self.config.patch_size
|
| 233 |
+
|
| 234 |
+
self.class_embedding = self.param("class_embedding", jax.nn.initializers.normal(stddev=0.02), (embed_dim,))
|
| 235 |
+
|
| 236 |
+
self.patch_embedding = nn.Conv(
|
| 237 |
+
embed_dim,
|
| 238 |
+
kernel_size=(patch_size, patch_size),
|
| 239 |
+
strides=(patch_size, patch_size),
|
| 240 |
+
padding="VALID",
|
| 241 |
+
use_bias=False,
|
| 242 |
+
dtype=self.dtype,
|
| 243 |
+
kernel_init=jax.nn.initializers.normal(),
|
| 244 |
+
)
|
| 245 |
+
|
| 246 |
+
self.num_patches = (image_size // patch_size) ** 2
|
| 247 |
+
num_positions = self.num_patches + 1
|
| 248 |
+
self.position_embedding = nn.Embed(num_positions, embed_dim, embedding_init=jax.nn.initializers.normal())
|
| 249 |
+
self.position_ids = jnp.expand_dims(jnp.arange(0, num_positions, dtype="i4"), axis=0)
|
| 250 |
+
|
| 251 |
+
def __call__(self, pixel_values):
|
| 252 |
+
patch_embeds = self.patch_embedding(pixel_values)
|
| 253 |
+
batch_size, height, width, channels = patch_embeds.shape
|
| 254 |
+
patch_embeds = jnp.reshape(patch_embeds, (batch_size, height * width, channels))
|
| 255 |
+
|
| 256 |
+
class_embeds = jnp.expand_dims(self.class_embedding, axis=(0, 1))
|
| 257 |
+
class_embeds = jnp.tile(class_embeds, (batch_size, 1, 1))
|
| 258 |
+
embeddings = jnp.concatenate([class_embeds, patch_embeds], axis=1)
|
| 259 |
+
embeddings = embeddings + self.position_embedding(self.position_ids)
|
| 260 |
+
return embeddings
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
class FlaxCLIPTextEmbeddings(nn.Module):
|
| 264 |
+
config: CLIPTextConfig
|
| 265 |
+
dtype: jnp.dtype = jnp.float32
|
| 266 |
+
|
| 267 |
+
def setup(self):
|
| 268 |
+
embed_dim = self.config.hidden_size
|
| 269 |
+
|
| 270 |
+
self.token_embedding = nn.Embed(self.config.vocab_size, embed_dim, embedding_init=jax.nn.initializers.normal())
|
| 271 |
+
self.position_embedding = nn.Embed(
|
| 272 |
+
self.config.max_position_embeddings, embed_dim, embedding_init=jax.nn.initializers.normal()
|
| 273 |
+
)
|
| 274 |
+
self.position_ids = jnp.expand_dims(
|
| 275 |
+
jnp.arange(0, self.config.max_position_embeddings, dtype="i4"), axis=(0, 1)
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
def __call__(self, input_ids, position_ids):
|
| 279 |
+
input_embeds = self.token_embedding(input_ids.astype("i4"))
|
| 280 |
+
position_embeds = self.position_embedding(position_ids.astype("i4"))
|
| 281 |
+
|
| 282 |
+
embeddings = input_embeds + position_embeds
|
| 283 |
+
return embeddings
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
class FlaxCLIPAttention(nn.Module):
|
| 287 |
+
config: Union[CLIPTextConfig, CLIPVisionConfig]
|
| 288 |
+
dtype: jnp.dtype = jnp.float32
|
| 289 |
+
|
| 290 |
+
def setup(self):
|
| 291 |
+
self.embed_dim = self.config.hidden_size
|
| 292 |
+
self.num_heads = self.config.num_attention_heads
|
| 293 |
+
self.head_dim = self.embed_dim // self.num_heads
|
| 294 |
+
if self.head_dim * self.num_heads != self.embed_dim:
|
| 295 |
+
raise ValueError(
|
| 296 |
+
f"embed_dim must be divisible by num_heads (got `embed_dim`: {self.embed_dim} and `num_heads`:"
|
| 297 |
+
f" {self.num_heads})."
|
| 298 |
+
)
|
| 299 |
+
self.scale = self.head_dim**-0.5
|
| 300 |
+
self.dropout = self.config.attention_dropout
|
| 301 |
+
|
| 302 |
+
self.k_proj = nn.Dense(self.embed_dim, dtype=self.dtype, kernel_init=jax.nn.initializers.normal(0.01))
|
| 303 |
+
self.v_proj = nn.Dense(self.embed_dim, dtype=self.dtype, kernel_init=jax.nn.initializers.normal(0.01))
|
| 304 |
+
self.q_proj = nn.Dense(self.embed_dim, dtype=self.dtype, kernel_init=jax.nn.initializers.normal(0.01))
|
| 305 |
+
self.out_proj = nn.Dense(self.embed_dim, dtype=self.dtype, kernel_init=jax.nn.initializers.normal(0.01))
|
| 306 |
+
|
| 307 |
+
self.causal = isinstance(self.config, CLIPTextConfig)
|
| 308 |
+
if self.causal:
|
| 309 |
+
self.causal_mask = make_causal_mask(jnp.ones((1, self.config.max_position_embeddings), dtype="i4"))
|
| 310 |
+
|
| 311 |
+
def _split_heads(self, hidden_states):
|
| 312 |
+
return hidden_states.reshape(hidden_states.shape[:2] + (self.num_heads, self.head_dim))
|
| 313 |
+
|
| 314 |
+
def _merge_heads(self, hidden_states):
|
| 315 |
+
return hidden_states.reshape(hidden_states.shape[:2] + (self.embed_dim,))
|
| 316 |
+
|
| 317 |
+
def __call__(
|
| 318 |
+
self,
|
| 319 |
+
hidden_states,
|
| 320 |
+
attention_mask=None,
|
| 321 |
+
deterministic: bool = True,
|
| 322 |
+
output_attentions: bool = False,
|
| 323 |
+
):
|
| 324 |
+
query = self.q_proj(hidden_states)
|
| 325 |
+
key = self.k_proj(hidden_states)
|
| 326 |
+
value = self.v_proj(hidden_states)
|
| 327 |
+
|
| 328 |
+
query = self._split_heads(query)
|
| 329 |
+
key = self._split_heads(key)
|
| 330 |
+
value = self._split_heads(value)
|
| 331 |
+
|
| 332 |
+
causal_attention_mask = None
|
| 333 |
+
if self.causal:
|
| 334 |
+
query_length, key_length = query.shape[1], key.shape[1]
|
| 335 |
+
causal_attention_mask = self.causal_mask[:, :, key_length - query_length : key_length, :key_length]
|
| 336 |
+
|
| 337 |
+
if attention_mask is not None and causal_attention_mask is not None:
|
| 338 |
+
attention_mask = jnp.expand_dims(attention_mask, axis=(-3, -2))
|
| 339 |
+
attention_mask = combine_masks(attention_mask, causal_attention_mask, dtype="i4")
|
| 340 |
+
elif causal_attention_mask is not None:
|
| 341 |
+
attention_mask = causal_attention_mask
|
| 342 |
+
elif attention_mask is not None:
|
| 343 |
+
attention_mask = jnp.expand_dims(attention_mask, axis=(-3, -2))
|
| 344 |
+
|
| 345 |
+
if attention_mask is not None:
|
| 346 |
+
attention_bias = lax.select(
|
| 347 |
+
attention_mask > 0,
|
| 348 |
+
jnp.full(attention_mask.shape, 0.0).astype(self.dtype),
|
| 349 |
+
jnp.full(attention_mask.shape, jnp.finfo(self.dtype).min).astype(self.dtype),
|
| 350 |
+
)
|
| 351 |
+
else:
|
| 352 |
+
attention_bias = None
|
| 353 |
+
|
| 354 |
+
dropout_rng = None
|
| 355 |
+
if not deterministic and self.dropout > 0.0:
|
| 356 |
+
dropout_rng = self.make_rng("dropout")
|
| 357 |
+
|
| 358 |
+
attn_weights = dot_product_attention_weights(
|
| 359 |
+
query,
|
| 360 |
+
key,
|
| 361 |
+
bias=attention_bias,
|
| 362 |
+
dropout_rng=dropout_rng,
|
| 363 |
+
dropout_rate=self.dropout,
|
| 364 |
+
deterministic=deterministic,
|
| 365 |
+
dtype=self.dtype,
|
| 366 |
+
precision=None,
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
+
attn_output = jnp.einsum("...hqk,...khd->...qhd", attn_weights, value)
|
| 370 |
+
attn_output = self._merge_heads(attn_output)
|
| 371 |
+
attn_output = self.out_proj(attn_output)
|
| 372 |
+
|
| 373 |
+
outputs = (attn_output, attn_weights) if output_attentions else (attn_output,)
|
| 374 |
+
return outputs
|
| 375 |
+
|
| 376 |
+
|
| 377 |
+
class FlaxCLIPMLP(nn.Module):
|
| 378 |
+
config: Union[CLIPTextConfig, CLIPVisionConfig]
|
| 379 |
+
dtype: jnp.dtype = jnp.float32
|
| 380 |
+
|
| 381 |
+
def setup(self):
|
| 382 |
+
self.activation_fn = ACT2FN[self.config.hidden_act]
|
| 383 |
+
self.fc1 = nn.Dense(
|
| 384 |
+
self.config.intermediate_size,
|
| 385 |
+
dtype=self.dtype,
|
| 386 |
+
kernel_init=jax.nn.initializers.normal(0.01),
|
| 387 |
+
)
|
| 388 |
+
self.fc2 = nn.Dense(self.config.hidden_size, dtype=self.dtype, kernel_init=jax.nn.initializers.normal(0.01))
|
| 389 |
+
|
| 390 |
+
def __call__(self, hidden_states):
|
| 391 |
+
hidden_states = self.fc1(hidden_states)
|
| 392 |
+
hidden_states = self.activation_fn(hidden_states)
|
| 393 |
+
hidden_states = self.fc2(hidden_states)
|
| 394 |
+
return hidden_states
|
| 395 |
+
|
| 396 |
+
|
| 397 |
+
class FlaxCLIPEncoderLayer(nn.Module):
|
| 398 |
+
config: Union[CLIPTextConfig, CLIPVisionConfig]
|
| 399 |
+
dtype: jnp.dtype = jnp.float32
|
| 400 |
+
|
| 401 |
+
def setup(self):
|
| 402 |
+
self.self_attn = FlaxCLIPAttention(self.config, dtype=self.dtype)
|
| 403 |
+
self.layer_norm1 = nn.LayerNorm(epsilon=self.config.layer_norm_eps, dtype=self.dtype)
|
| 404 |
+
self.mlp = FlaxCLIPMLP(self.config, dtype=self.dtype)
|
| 405 |
+
self.layer_norm2 = nn.LayerNorm(epsilon=self.config.layer_norm_eps, dtype=self.dtype)
|
| 406 |
+
|
| 407 |
+
def __call__(
|
| 408 |
+
self,
|
| 409 |
+
hidden_states,
|
| 410 |
+
attention_mask,
|
| 411 |
+
deterministic: bool = True,
|
| 412 |
+
output_attentions: bool = False,
|
| 413 |
+
):
|
| 414 |
+
residual = hidden_states
|
| 415 |
+
|
| 416 |
+
hidden_states = self.layer_norm1(hidden_states)
|
| 417 |
+
attn_outputs = self.self_attn(
|
| 418 |
+
hidden_states=hidden_states,
|
| 419 |
+
attention_mask=attention_mask,
|
| 420 |
+
deterministic=deterministic,
|
| 421 |
+
output_attentions=output_attentions,
|
| 422 |
+
)
|
| 423 |
+
hidden_states = attn_outputs[0]
|
| 424 |
+
hidden_states = residual + hidden_states
|
| 425 |
+
|
| 426 |
+
residual = hidden_states
|
| 427 |
+
hidden_states = self.layer_norm2(hidden_states)
|
| 428 |
+
hidden_states = self.mlp(hidden_states)
|
| 429 |
+
hidden_states = residual + hidden_states
|
| 430 |
+
|
| 431 |
+
outputs = (hidden_states,)
|
| 432 |
+
|
| 433 |
+
if output_attentions:
|
| 434 |
+
outputs += attn_outputs[1:]
|
| 435 |
+
|
| 436 |
+
return outputs
|
| 437 |
+
|
| 438 |
+
|
| 439 |
+
class FlaxCLIPLayerCollection(nn.Module):
|
| 440 |
+
config: Union[CLIPTextConfig, CLIPVisionConfig]
|
| 441 |
+
dtype: jnp.dtype = jnp.float32
|
| 442 |
+
|
| 443 |
+
def setup(self):
|
| 444 |
+
self.layers = [
|
| 445 |
+
FlaxCLIPEncoderLayer(self.config, name=str(i), dtype=self.dtype)
|
| 446 |
+
for i in range(self.config.num_hidden_layers)
|
| 447 |
+
]
|
| 448 |
+
|
| 449 |
+
def __call__(
|
| 450 |
+
self,
|
| 451 |
+
hidden_states,
|
| 452 |
+
attention_mask=None,
|
| 453 |
+
deterministic: bool = True,
|
| 454 |
+
output_attentions: bool = False,
|
| 455 |
+
output_hidden_states: bool = False,
|
| 456 |
+
return_dict: bool = True,
|
| 457 |
+
):
|
| 458 |
+
all_attentions = () if output_attentions else None
|
| 459 |
+
all_hidden_states = () if output_hidden_states else None
|
| 460 |
+
|
| 461 |
+
for layer in self.layers:
|
| 462 |
+
if output_hidden_states:
|
| 463 |
+
all_hidden_states += (hidden_states,)
|
| 464 |
+
|
| 465 |
+
layer_outputs = layer(
|
| 466 |
+
hidden_states, attention_mask, deterministic=deterministic, output_attentions=output_attentions
|
| 467 |
+
)
|
| 468 |
+
hidden_states = layer_outputs[0]
|
| 469 |
+
|
| 470 |
+
if output_attentions:
|
| 471 |
+
all_attentions += (layer_outputs[1],)
|
| 472 |
+
|
| 473 |
+
if output_hidden_states:
|
| 474 |
+
all_hidden_states += (hidden_states,)
|
| 475 |
+
|
| 476 |
+
outputs = (hidden_states,)
|
| 477 |
+
|
| 478 |
+
if not return_dict:
|
| 479 |
+
return tuple(v for v in outputs if v is not None)
|
| 480 |
+
|
| 481 |
+
return FlaxBaseModelOutput(
|
| 482 |
+
last_hidden_state=hidden_states, hidden_states=all_hidden_states, attentions=all_attentions
|
| 483 |
+
)
|
| 484 |
+
|
| 485 |
+
|
| 486 |
+
class FlaxCLIPEncoder(nn.Module):
|
| 487 |
+
config: Union[CLIPTextConfig, CLIPVisionConfig]
|
| 488 |
+
dtype: jnp.dtype = jnp.float32
|
| 489 |
+
|
| 490 |
+
def setup(self):
|
| 491 |
+
self.layers = FlaxCLIPLayerCollection(self.config, dtype=self.dtype)
|
| 492 |
+
|
| 493 |
+
def __call__(
|
| 494 |
+
self,
|
| 495 |
+
inputs_embeds,
|
| 496 |
+
attention_mask=None,
|
| 497 |
+
deterministic: bool = True,
|
| 498 |
+
output_attentions: bool = False,
|
| 499 |
+
output_hidden_states: bool = False,
|
| 500 |
+
return_dict: bool = True,
|
| 501 |
+
):
|
| 502 |
+
return self.layers(
|
| 503 |
+
hidden_states=inputs_embeds,
|
| 504 |
+
attention_mask=attention_mask,
|
| 505 |
+
deterministic=deterministic,
|
| 506 |
+
output_attentions=output_attentions,
|
| 507 |
+
output_hidden_states=output_hidden_states,
|
| 508 |
+
return_dict=return_dict,
|
| 509 |
+
)
|
| 510 |
+
|
| 511 |
+
|
| 512 |
+
class FlaxCLIPTextTransformer(nn.Module):
|
| 513 |
+
config: CLIPTextConfig
|
| 514 |
+
dtype: jnp.dtype = jnp.float32
|
| 515 |
+
|
| 516 |
+
def setup(self):
|
| 517 |
+
self.embeddings = FlaxCLIPTextEmbeddings(self.config, dtype=self.dtype)
|
| 518 |
+
self.encoder = FlaxCLIPEncoder(self.config, dtype=self.dtype)
|
| 519 |
+
self.final_layer_norm = nn.LayerNorm(epsilon=self.config.layer_norm_eps, dtype=self.dtype)
|
| 520 |
+
|
| 521 |
+
# For `pooled_output` computation
|
| 522 |
+
self.eos_token_id = self.config.eos_token_id
|
| 523 |
+
|
| 524 |
+
def __call__(
|
| 525 |
+
self,
|
| 526 |
+
input_ids,
|
| 527 |
+
attention_mask,
|
| 528 |
+
position_ids,
|
| 529 |
+
deterministic: bool = True,
|
| 530 |
+
output_attentions: bool = False,
|
| 531 |
+
output_hidden_states: bool = False,
|
| 532 |
+
return_dict: bool = True,
|
| 533 |
+
):
|
| 534 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 535 |
+
output_hidden_states = (
|
| 536 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 537 |
+
)
|
| 538 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 539 |
+
|
| 540 |
+
hidden_states = self.embeddings(input_ids=input_ids, position_ids=position_ids)
|
| 541 |
+
|
| 542 |
+
encoder_outputs = self.encoder(
|
| 543 |
+
inputs_embeds=hidden_states,
|
| 544 |
+
attention_mask=attention_mask,
|
| 545 |
+
deterministic=deterministic,
|
| 546 |
+
output_attentions=output_attentions,
|
| 547 |
+
output_hidden_states=output_hidden_states,
|
| 548 |
+
return_dict=return_dict,
|
| 549 |
+
)
|
| 550 |
+
|
| 551 |
+
last_hidden_state = encoder_outputs[0]
|
| 552 |
+
last_hidden_state = self.final_layer_norm(last_hidden_state)
|
| 553 |
+
|
| 554 |
+
if self.eos_token_id == 2:
|
| 555 |
+
# The `eos_token_id` was incorrect before PR #24773: Let's keep what have been done here.
|
| 556 |
+
# A CLIP model with such `eos_token_id` in the config can't work correctly with extra new tokens added
|
| 557 |
+
# ------------------------------------------------------------
|
| 558 |
+
# text_embeds.shape = [batch_size, sequence_length, transformer.width]
|
| 559 |
+
# take features from the EOS embedding (eos_token_id is the highest number in each sequence)
|
| 560 |
+
pooled_output = last_hidden_state[jnp.arange(last_hidden_state.shape[0]), input_ids.argmax(axis=-1)]
|
| 561 |
+
else:
|
| 562 |
+
# (no need to cast from bool to int after comparing to `eos_token_id`)
|
| 563 |
+
pooled_output = last_hidden_state[
|
| 564 |
+
jnp.arange(last_hidden_state.shape[0]), (input_ids == self.eos_token_id).argmax(axis=-1)
|
| 565 |
+
]
|
| 566 |
+
|
| 567 |
+
if not return_dict:
|
| 568 |
+
return (last_hidden_state, pooled_output) + encoder_outputs[1:]
|
| 569 |
+
|
| 570 |
+
return FlaxBaseModelOutputWithPooling(
|
| 571 |
+
last_hidden_state=last_hidden_state,
|
| 572 |
+
pooler_output=pooled_output,
|
| 573 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 574 |
+
attentions=encoder_outputs.attentions,
|
| 575 |
+
)
|
| 576 |
+
|
| 577 |
+
|
| 578 |
+
class FlaxCLIPVisionTransformer(nn.Module):
|
| 579 |
+
config: CLIPVisionConfig
|
| 580 |
+
dtype: jnp.dtype = jnp.float32
|
| 581 |
+
|
| 582 |
+
def setup(self):
|
| 583 |
+
self.embeddings = FlaxCLIPVisionEmbeddings(self.config, dtype=self.dtype)
|
| 584 |
+
self.pre_layrnorm = nn.LayerNorm(epsilon=self.config.layer_norm_eps, dtype=self.dtype)
|
| 585 |
+
self.encoder = FlaxCLIPEncoder(self.config, dtype=self.dtype)
|
| 586 |
+
self.post_layernorm = nn.LayerNorm(epsilon=self.config.layer_norm_eps, dtype=self.dtype)
|
| 587 |
+
|
| 588 |
+
def __call__(
|
| 589 |
+
self,
|
| 590 |
+
pixel_values=None,
|
| 591 |
+
deterministic: bool = True,
|
| 592 |
+
output_attentions=None,
|
| 593 |
+
output_hidden_states=None,
|
| 594 |
+
return_dict: bool = True,
|
| 595 |
+
):
|
| 596 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 597 |
+
output_hidden_states = (
|
| 598 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 599 |
+
)
|
| 600 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 601 |
+
|
| 602 |
+
hidden_states = self.embeddings(pixel_values)
|
| 603 |
+
hidden_states = self.pre_layrnorm(hidden_states)
|
| 604 |
+
|
| 605 |
+
encoder_outputs = self.encoder(
|
| 606 |
+
inputs_embeds=hidden_states,
|
| 607 |
+
deterministic=deterministic,
|
| 608 |
+
output_attentions=output_attentions,
|
| 609 |
+
output_hidden_states=output_hidden_states,
|
| 610 |
+
return_dict=return_dict,
|
| 611 |
+
)
|
| 612 |
+
|
| 613 |
+
last_hidden_state = encoder_outputs[0]
|
| 614 |
+
pooled_output = last_hidden_state[:, 0, :]
|
| 615 |
+
pooled_output = self.post_layernorm(pooled_output)
|
| 616 |
+
|
| 617 |
+
if not return_dict:
|
| 618 |
+
return (last_hidden_state, pooled_output) + encoder_outputs[1:]
|
| 619 |
+
|
| 620 |
+
return FlaxBaseModelOutputWithPooling(
|
| 621 |
+
last_hidden_state=last_hidden_state,
|
| 622 |
+
pooler_output=pooled_output,
|
| 623 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 624 |
+
attentions=encoder_outputs.attentions,
|
| 625 |
+
)
|
| 626 |
+
|
| 627 |
+
|
| 628 |
+
class FlaxCLIPTextPreTrainedModel(FlaxPreTrainedModel):
|
| 629 |
+
config_class = CLIPTextConfig
|
| 630 |
+
module_class: nn.Module = None
|
| 631 |
+
|
| 632 |
+
def __init__(
|
| 633 |
+
self,
|
| 634 |
+
config: CLIPTextConfig,
|
| 635 |
+
input_shape=(1, 1),
|
| 636 |
+
seed: int = 0,
|
| 637 |
+
dtype: jnp.dtype = jnp.float32,
|
| 638 |
+
_do_init: bool = True,
|
| 639 |
+
**kwargs,
|
| 640 |
+
):
|
| 641 |
+
module = self.module_class(config=config, dtype=dtype, **kwargs)
|
| 642 |
+
super().__init__(config, module, input_shape=input_shape, seed=seed, dtype=dtype, _do_init=_do_init)
|
| 643 |
+
|
| 644 |
+
def init_weights(self, rng: jax.random.PRNGKey, input_shape: Tuple, params: FrozenDict = None) -> FrozenDict:
|
| 645 |
+
# init input tensor
|
| 646 |
+
input_ids = jnp.zeros(input_shape, dtype="i4")
|
| 647 |
+
position_ids = jnp.broadcast_to(jnp.arange(jnp.atleast_2d(input_ids).shape[-1]), input_shape)
|
| 648 |
+
attention_mask = jnp.ones_like(input_ids)
|
| 649 |
+
|
| 650 |
+
params_rng, dropout_rng = jax.random.split(rng)
|
| 651 |
+
rngs = {"params": params_rng, "dropout": dropout_rng}
|
| 652 |
+
|
| 653 |
+
random_params = self.module.init(rngs, input_ids, attention_mask, position_ids)["params"]
|
| 654 |
+
|
| 655 |
+
if params is not None:
|
| 656 |
+
random_params = flatten_dict(unfreeze(random_params))
|
| 657 |
+
params = flatten_dict(unfreeze(params))
|
| 658 |
+
for missing_key in self._missing_keys:
|
| 659 |
+
params[missing_key] = random_params[missing_key]
|
| 660 |
+
self._missing_keys = set()
|
| 661 |
+
return freeze(unflatten_dict(params))
|
| 662 |
+
else:
|
| 663 |
+
return random_params
|
| 664 |
+
|
| 665 |
+
def __call__(
|
| 666 |
+
self,
|
| 667 |
+
input_ids,
|
| 668 |
+
attention_mask=None,
|
| 669 |
+
position_ids=None,
|
| 670 |
+
params: dict = None,
|
| 671 |
+
dropout_rng: jax.random.PRNGKey = None,
|
| 672 |
+
train: bool = False,
|
| 673 |
+
output_attentions: Optional[bool] = None,
|
| 674 |
+
output_hidden_states: Optional[bool] = None,
|
| 675 |
+
return_dict: Optional[bool] = None,
|
| 676 |
+
):
|
| 677 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 678 |
+
output_hidden_states = (
|
| 679 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 680 |
+
)
|
| 681 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 682 |
+
|
| 683 |
+
if position_ids is None:
|
| 684 |
+
position_ids = jnp.broadcast_to(jnp.arange(jnp.atleast_2d(input_ids).shape[-1]), input_ids.shape)
|
| 685 |
+
|
| 686 |
+
if attention_mask is None:
|
| 687 |
+
attention_mask = jnp.ones_like(input_ids)
|
| 688 |
+
|
| 689 |
+
# Handle any PRNG if needed
|
| 690 |
+
rngs = {}
|
| 691 |
+
if dropout_rng is not None:
|
| 692 |
+
rngs["dropout"] = dropout_rng
|
| 693 |
+
|
| 694 |
+
return self.module.apply(
|
| 695 |
+
{"params": params or self.params},
|
| 696 |
+
jnp.array(input_ids, dtype="i4"),
|
| 697 |
+
jnp.array(attention_mask, dtype="i4"),
|
| 698 |
+
jnp.array(position_ids, dtype="i4"),
|
| 699 |
+
not train,
|
| 700 |
+
output_attentions,
|
| 701 |
+
output_hidden_states,
|
| 702 |
+
return_dict,
|
| 703 |
+
rngs=rngs,
|
| 704 |
+
)
|
| 705 |
+
|
| 706 |
+
|
| 707 |
+
class FlaxCLIPVisionPreTrainedModel(FlaxPreTrainedModel):
|
| 708 |
+
config_class = CLIPVisionConfig
|
| 709 |
+
main_input_name = "pixel_values"
|
| 710 |
+
module_class: nn.Module = None
|
| 711 |
+
|
| 712 |
+
def __init__(
|
| 713 |
+
self,
|
| 714 |
+
config: CLIPVisionConfig,
|
| 715 |
+
input_shape: Optional[Tuple] = None,
|
| 716 |
+
seed: int = 0,
|
| 717 |
+
dtype: jnp.dtype = jnp.float32,
|
| 718 |
+
_do_init: bool = True,
|
| 719 |
+
**kwargs,
|
| 720 |
+
):
|
| 721 |
+
if input_shape is None:
|
| 722 |
+
input_shape = (1, config.image_size, config.image_size, 3)
|
| 723 |
+
module = self.module_class(config=config, dtype=dtype, **kwargs)
|
| 724 |
+
super().__init__(config, module, input_shape=input_shape, seed=seed, dtype=dtype, _do_init=_do_init)
|
| 725 |
+
|
| 726 |
+
def init_weights(self, rng: jax.random.PRNGKey, input_shape: Tuple, params: FrozenDict = None) -> FrozenDict:
|
| 727 |
+
# init input tensor
|
| 728 |
+
pixel_values = jax.random.normal(rng, input_shape)
|
| 729 |
+
|
| 730 |
+
params_rng, dropout_rng = jax.random.split(rng)
|
| 731 |
+
rngs = {"params": params_rng, "dropout": dropout_rng}
|
| 732 |
+
|
| 733 |
+
random_params = self.module.init(rngs, pixel_values)["params"]
|
| 734 |
+
|
| 735 |
+
if params is not None:
|
| 736 |
+
random_params = flatten_dict(unfreeze(random_params))
|
| 737 |
+
params = flatten_dict(unfreeze(params))
|
| 738 |
+
for missing_key in self._missing_keys:
|
| 739 |
+
params[missing_key] = random_params[missing_key]
|
| 740 |
+
self._missing_keys = set()
|
| 741 |
+
return freeze(unflatten_dict(params))
|
| 742 |
+
else:
|
| 743 |
+
return random_params
|
| 744 |
+
|
| 745 |
+
def __call__(
|
| 746 |
+
self,
|
| 747 |
+
pixel_values,
|
| 748 |
+
params: dict = None,
|
| 749 |
+
dropout_rng: jax.random.PRNGKey = None,
|
| 750 |
+
train: bool = False,
|
| 751 |
+
output_attentions: Optional[bool] = None,
|
| 752 |
+
output_hidden_states: Optional[bool] = None,
|
| 753 |
+
return_dict: Optional[bool] = None,
|
| 754 |
+
):
|
| 755 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 756 |
+
output_hidden_states = (
|
| 757 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 758 |
+
)
|
| 759 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 760 |
+
|
| 761 |
+
pixel_values = jnp.transpose(pixel_values, (0, 2, 3, 1))
|
| 762 |
+
|
| 763 |
+
# Handle any PRNG if needed
|
| 764 |
+
rngs = {}
|
| 765 |
+
if dropout_rng is not None:
|
| 766 |
+
rngs["dropout"] = dropout_rng
|
| 767 |
+
|
| 768 |
+
return self.module.apply(
|
| 769 |
+
{"params": params or self.params},
|
| 770 |
+
jnp.array(pixel_values, dtype=jnp.float32),
|
| 771 |
+
not train,
|
| 772 |
+
output_attentions,
|
| 773 |
+
output_hidden_states,
|
| 774 |
+
return_dict,
|
| 775 |
+
rngs=rngs,
|
| 776 |
+
)
|
| 777 |
+
|
| 778 |
+
|
| 779 |
+
class FlaxCLIPPreTrainedModel(FlaxPreTrainedModel):
|
| 780 |
+
config_class = CLIPConfig
|
| 781 |
+
module_class: nn.Module = None
|
| 782 |
+
|
| 783 |
+
def __init__(
|
| 784 |
+
self,
|
| 785 |
+
config: CLIPConfig,
|
| 786 |
+
input_shape: Optional[Tuple] = None,
|
| 787 |
+
seed: int = 0,
|
| 788 |
+
dtype: jnp.dtype = jnp.float32,
|
| 789 |
+
_do_init: bool = True,
|
| 790 |
+
**kwargs,
|
| 791 |
+
):
|
| 792 |
+
if input_shape is None:
|
| 793 |
+
input_shape = ((1, 1), (1, config.vision_config.image_size, config.vision_config.image_size, 3))
|
| 794 |
+
module = self.module_class(config=config, dtype=dtype, **kwargs)
|
| 795 |
+
super().__init__(config, module, input_shape=input_shape, seed=seed, dtype=dtype, _do_init=_do_init)
|
| 796 |
+
|
| 797 |
+
def init_weights(self, rng: jax.random.PRNGKey, input_shape: Tuple, params: FrozenDict = None) -> FrozenDict:
|
| 798 |
+
# init input tensor
|
| 799 |
+
input_ids = jnp.zeros(input_shape[0], dtype="i4")
|
| 800 |
+
position_ids = jnp.broadcast_to(jnp.arange(jnp.atleast_2d(input_ids).shape[-1]), input_shape[0])
|
| 801 |
+
attention_mask = jnp.ones_like(input_ids)
|
| 802 |
+
|
| 803 |
+
pixel_values = jax.random.normal(rng, input_shape[1])
|
| 804 |
+
|
| 805 |
+
params_rng, dropout_rng = jax.random.split(rng)
|
| 806 |
+
rngs = {"params": params_rng, "dropout": dropout_rng}
|
| 807 |
+
|
| 808 |
+
random_params = self.module.init(rngs, input_ids, pixel_values, attention_mask, position_ids)["params"]
|
| 809 |
+
|
| 810 |
+
if params is not None:
|
| 811 |
+
random_params = flatten_dict(unfreeze(random_params))
|
| 812 |
+
params = flatten_dict(unfreeze(params))
|
| 813 |
+
for missing_key in self._missing_keys:
|
| 814 |
+
params[missing_key] = random_params[missing_key]
|
| 815 |
+
self._missing_keys = set()
|
| 816 |
+
return freeze(unflatten_dict(params))
|
| 817 |
+
else:
|
| 818 |
+
return random_params
|
| 819 |
+
|
| 820 |
+
def __call__(
|
| 821 |
+
self,
|
| 822 |
+
input_ids,
|
| 823 |
+
pixel_values,
|
| 824 |
+
attention_mask=None,
|
| 825 |
+
position_ids=None,
|
| 826 |
+
params: dict = None,
|
| 827 |
+
dropout_rng: jax.random.PRNGKey = None,
|
| 828 |
+
train: bool = False,
|
| 829 |
+
output_attentions: Optional[bool] = None,
|
| 830 |
+
output_hidden_states: Optional[bool] = None,
|
| 831 |
+
return_dict: Optional[bool] = None,
|
| 832 |
+
):
|
| 833 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 834 |
+
output_hidden_states = (
|
| 835 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 836 |
+
)
|
| 837 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 838 |
+
|
| 839 |
+
if position_ids is None:
|
| 840 |
+
position_ids = jnp.broadcast_to(jnp.arange(jnp.atleast_2d(input_ids).shape[-1]), input_ids.shape)
|
| 841 |
+
|
| 842 |
+
if attention_mask is None:
|
| 843 |
+
attention_mask = jnp.ones_like(input_ids)
|
| 844 |
+
|
| 845 |
+
pixel_values = jnp.transpose(pixel_values, (0, 2, 3, 1))
|
| 846 |
+
|
| 847 |
+
# Handle any PRNG if needed
|
| 848 |
+
rngs = {}
|
| 849 |
+
if dropout_rng is not None:
|
| 850 |
+
rngs["dropout"] = dropout_rng
|
| 851 |
+
|
| 852 |
+
return self.module.apply(
|
| 853 |
+
{"params": params or self.params},
|
| 854 |
+
jnp.array(input_ids, dtype="i4"),
|
| 855 |
+
jnp.array(pixel_values, dtype=jnp.float32),
|
| 856 |
+
jnp.array(attention_mask, dtype="i4"),
|
| 857 |
+
jnp.array(position_ids, dtype="i4"),
|
| 858 |
+
not train,
|
| 859 |
+
output_attentions,
|
| 860 |
+
output_hidden_states,
|
| 861 |
+
return_dict,
|
| 862 |
+
rngs=rngs,
|
| 863 |
+
)
|
| 864 |
+
|
| 865 |
+
def get_text_features(
|
| 866 |
+
self,
|
| 867 |
+
input_ids,
|
| 868 |
+
attention_mask=None,
|
| 869 |
+
position_ids=None,
|
| 870 |
+
params: dict = None,
|
| 871 |
+
dropout_rng: jax.random.PRNGKey = None,
|
| 872 |
+
train=False,
|
| 873 |
+
):
|
| 874 |
+
r"""
|
| 875 |
+
Args:
|
| 876 |
+
input_ids (`numpy.ndarray` of shape `(batch_size, sequence_length)`):
|
| 877 |
+
Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you
|
| 878 |
+
provide it.
|
| 879 |
+
|
| 880 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 881 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 882 |
+
|
| 883 |
+
[What are input IDs?](../glossary#input-ids)
|
| 884 |
+
|
| 885 |
+
Returns:
|
| 886 |
+
text_features (`jnp.ndarray` of shape `(batch_size, output_dim`): The text embeddings obtained by applying
|
| 887 |
+
the projection layer to the pooled output of [`FlaxCLIPTextModel`].
|
| 888 |
+
|
| 889 |
+
Examples:
|
| 890 |
+
|
| 891 |
+
```python
|
| 892 |
+
>>> from transformers import AutoTokenizer, FlaxCLIPModel
|
| 893 |
+
|
| 894 |
+
>>> model = FlaxCLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 895 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 896 |
+
|
| 897 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="np")
|
| 898 |
+
>>> text_features = model.get_text_features(**inputs)
|
| 899 |
+
```"""
|
| 900 |
+
if position_ids is None:
|
| 901 |
+
position_ids = jnp.broadcast_to(jnp.arange(jnp.atleast_2d(input_ids).shape[-1]), input_ids.shape)
|
| 902 |
+
|
| 903 |
+
if attention_mask is None:
|
| 904 |
+
attention_mask = jnp.ones_like(input_ids)
|
| 905 |
+
|
| 906 |
+
# Handle any PRNG if needed
|
| 907 |
+
rngs = {}
|
| 908 |
+
if dropout_rng is not None:
|
| 909 |
+
rngs["dropout"] = dropout_rng
|
| 910 |
+
|
| 911 |
+
def _get_features(module, input_ids, attention_mask, position_ids, deterministic):
|
| 912 |
+
text_outputs = module.text_model(
|
| 913 |
+
input_ids=input_ids,
|
| 914 |
+
attention_mask=attention_mask,
|
| 915 |
+
position_ids=position_ids,
|
| 916 |
+
deterministic=deterministic,
|
| 917 |
+
)
|
| 918 |
+
pooled_output = text_outputs[1]
|
| 919 |
+
text_features = module.text_projection(pooled_output)
|
| 920 |
+
return text_features
|
| 921 |
+
|
| 922 |
+
return self.module.apply(
|
| 923 |
+
{"params": params or self.params},
|
| 924 |
+
jnp.array(input_ids, dtype="i4"),
|
| 925 |
+
jnp.array(attention_mask, dtype="i4"),
|
| 926 |
+
jnp.array(position_ids, dtype="i4"),
|
| 927 |
+
not train,
|
| 928 |
+
method=_get_features,
|
| 929 |
+
rngs=rngs,
|
| 930 |
+
)
|
| 931 |
+
|
| 932 |
+
def get_image_features(
|
| 933 |
+
self, pixel_values, params: dict = None, dropout_rng: jax.random.PRNGKey = None, train=False
|
| 934 |
+
):
|
| 935 |
+
r"""
|
| 936 |
+
Args:
|
| 937 |
+
pixel_values (`numpy.ndarray` of shape `(batch_size, num_channels, height, width)`):
|
| 938 |
+
Pixel values. Padding will be ignored by default should you provide it. Pixel values can be obtained
|
| 939 |
+
using [`AutoImageProcessor`]. See [`CLIPImageProcessor.__call__`] for details.
|
| 940 |
+
|
| 941 |
+
Returns:
|
| 942 |
+
image_features (`jnp.ndarray` of shape `(batch_size, output_dim`): The image embeddings obtained by
|
| 943 |
+
applying the projection layer to the pooled output of [`FlaxCLIPVisionModel`]
|
| 944 |
+
|
| 945 |
+
Examples:
|
| 946 |
+
|
| 947 |
+
```python
|
| 948 |
+
>>> from PIL import Image
|
| 949 |
+
>>> import requests
|
| 950 |
+
>>> from transformers import AutoProcessor, FlaxCLIPModel
|
| 951 |
+
|
| 952 |
+
>>> model = FlaxCLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 953 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 954 |
+
|
| 955 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 956 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 957 |
+
|
| 958 |
+
>>> inputs = processor(images=image, return_tensors="np")
|
| 959 |
+
|
| 960 |
+
>>> image_features = model.get_image_features(**inputs)
|
| 961 |
+
```"""
|
| 962 |
+
pixel_values = jnp.transpose(pixel_values, (0, 2, 3, 1))
|
| 963 |
+
|
| 964 |
+
# Handle any PRNG if needed
|
| 965 |
+
rngs = {}
|
| 966 |
+
if dropout_rng is not None:
|
| 967 |
+
rngs["dropout"] = dropout_rng
|
| 968 |
+
|
| 969 |
+
def _get_features(module, pixel_values, deterministic):
|
| 970 |
+
vision_outputs = module.vision_model(pixel_values=pixel_values, deterministic=deterministic)
|
| 971 |
+
pooled_output = vision_outputs[1] # pooled_output
|
| 972 |
+
image_features = module.visual_projection(pooled_output)
|
| 973 |
+
return image_features
|
| 974 |
+
|
| 975 |
+
return self.module.apply(
|
| 976 |
+
{"params": params or self.params},
|
| 977 |
+
jnp.array(pixel_values, dtype=jnp.float32),
|
| 978 |
+
not train,
|
| 979 |
+
method=_get_features,
|
| 980 |
+
rngs=rngs,
|
| 981 |
+
)
|
| 982 |
+
|
| 983 |
+
|
| 984 |
+
class FlaxCLIPTextModule(nn.Module):
|
| 985 |
+
config: CLIPTextConfig
|
| 986 |
+
dtype: jnp.dtype = jnp.float32
|
| 987 |
+
|
| 988 |
+
def setup(self):
|
| 989 |
+
self.text_model = FlaxCLIPTextTransformer(self.config, dtype=self.dtype)
|
| 990 |
+
|
| 991 |
+
def __call__(
|
| 992 |
+
self,
|
| 993 |
+
input_ids,
|
| 994 |
+
attention_mask,
|
| 995 |
+
position_ids,
|
| 996 |
+
deterministic: bool = True,
|
| 997 |
+
output_attentions: bool = False,
|
| 998 |
+
output_hidden_states: bool = False,
|
| 999 |
+
return_dict: bool = True,
|
| 1000 |
+
):
|
| 1001 |
+
return self.text_model(
|
| 1002 |
+
input_ids=input_ids,
|
| 1003 |
+
attention_mask=attention_mask,
|
| 1004 |
+
position_ids=position_ids,
|
| 1005 |
+
deterministic=deterministic,
|
| 1006 |
+
output_attentions=output_attentions,
|
| 1007 |
+
output_hidden_states=output_hidden_states,
|
| 1008 |
+
return_dict=return_dict,
|
| 1009 |
+
)
|
| 1010 |
+
|
| 1011 |
+
|
| 1012 |
+
class FlaxCLIPTextModel(FlaxCLIPTextPreTrainedModel):
|
| 1013 |
+
module_class = FlaxCLIPTextModule
|
| 1014 |
+
|
| 1015 |
+
|
| 1016 |
+
FLAX_CLIP_TEXT_MODEL_DOCSTRING = """
|
| 1017 |
+
Returns:
|
| 1018 |
+
|
| 1019 |
+
Example:
|
| 1020 |
+
|
| 1021 |
+
```python
|
| 1022 |
+
>>> from transformers import AutoTokenizer, FlaxCLIPTextModel
|
| 1023 |
+
|
| 1024 |
+
>>> model = FlaxCLIPTextModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1025 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 1026 |
+
|
| 1027 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="np")
|
| 1028 |
+
|
| 1029 |
+
>>> outputs = model(**inputs)
|
| 1030 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 1031 |
+
>>> pooler_output = outputs.pooler_output # pooled (EOS token) states
|
| 1032 |
+
```
|
| 1033 |
+
"""
|
| 1034 |
+
|
| 1035 |
+
overwrite_call_docstring(FlaxCLIPTextModel, CLIP_TEXT_INPUTS_DOCSTRING + FLAX_CLIP_TEXT_MODEL_DOCSTRING)
|
| 1036 |
+
append_replace_return_docstrings(
|
| 1037 |
+
FlaxCLIPTextModel, output_type=FlaxBaseModelOutputWithPooling, config_class=CLIPTextConfig
|
| 1038 |
+
)
|
| 1039 |
+
|
| 1040 |
+
|
| 1041 |
+
class FlaxCLIPTextModelWithProjectionModule(nn.Module):
|
| 1042 |
+
config: CLIPTextConfig
|
| 1043 |
+
dtype: jnp.dtype = jnp.float32
|
| 1044 |
+
|
| 1045 |
+
def setup(self):
|
| 1046 |
+
self.text_model = FlaxCLIPTextTransformer(self.config, dtype=self.dtype)
|
| 1047 |
+
self.text_projection = nn.Dense(self.config.projection_dim, use_bias=False, dtype=self.dtype)
|
| 1048 |
+
|
| 1049 |
+
def __call__(
|
| 1050 |
+
self,
|
| 1051 |
+
input_ids,
|
| 1052 |
+
attention_mask,
|
| 1053 |
+
position_ids,
|
| 1054 |
+
deterministic: bool = True,
|
| 1055 |
+
output_attentions: bool = False,
|
| 1056 |
+
output_hidden_states: bool = False,
|
| 1057 |
+
return_dict: bool = True,
|
| 1058 |
+
):
|
| 1059 |
+
text_outputs = self.text_model(
|
| 1060 |
+
input_ids=input_ids,
|
| 1061 |
+
attention_mask=attention_mask,
|
| 1062 |
+
position_ids=position_ids,
|
| 1063 |
+
deterministic=deterministic,
|
| 1064 |
+
output_attentions=output_attentions,
|
| 1065 |
+
output_hidden_states=output_hidden_states,
|
| 1066 |
+
return_dict=return_dict,
|
| 1067 |
+
)
|
| 1068 |
+
|
| 1069 |
+
pooled_output = text_outputs[1]
|
| 1070 |
+
text_embeds = self.text_projection(pooled_output)
|
| 1071 |
+
|
| 1072 |
+
if not return_dict:
|
| 1073 |
+
return (text_embeds, text_outputs[0]) + text_outputs[2:]
|
| 1074 |
+
|
| 1075 |
+
return FlaxCLIPTextModelOutput(
|
| 1076 |
+
text_embeds=text_embeds,
|
| 1077 |
+
last_hidden_state=text_outputs.last_hidden_state,
|
| 1078 |
+
hidden_states=text_outputs.hidden_states,
|
| 1079 |
+
attentions=text_outputs.attentions,
|
| 1080 |
+
)
|
| 1081 |
+
|
| 1082 |
+
|
| 1083 |
+
class FlaxCLIPTextModelWithProjection(FlaxCLIPTextPreTrainedModel):
|
| 1084 |
+
module_class = FlaxCLIPTextModelWithProjectionModule
|
| 1085 |
+
|
| 1086 |
+
|
| 1087 |
+
FLAX_CLIP_TEXT_MODEL_WITH_PROJECTION_DOCSTRING = """
|
| 1088 |
+
Returns:
|
| 1089 |
+
|
| 1090 |
+
Example:
|
| 1091 |
+
|
| 1092 |
+
```python
|
| 1093 |
+
>>> from transformers import AutoTokenizer, FlaxCLIPTextModelWithProjection
|
| 1094 |
+
|
| 1095 |
+
>>> model = FlaxCLIPTextModelWithProjection.from_pretrained("openai/clip-vit-base-patch32")
|
| 1096 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 1097 |
+
|
| 1098 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="np")
|
| 1099 |
+
|
| 1100 |
+
>>> outputs = model(**inputs)
|
| 1101 |
+
>>> text_embeds = outputs.text_embeds
|
| 1102 |
+
```
|
| 1103 |
+
"""
|
| 1104 |
+
|
| 1105 |
+
overwrite_call_docstring(
|
| 1106 |
+
FlaxCLIPTextModelWithProjection, CLIP_TEXT_INPUTS_DOCSTRING + FLAX_CLIP_TEXT_MODEL_WITH_PROJECTION_DOCSTRING
|
| 1107 |
+
)
|
| 1108 |
+
append_replace_return_docstrings(
|
| 1109 |
+
FlaxCLIPTextModelWithProjection, output_type=FlaxCLIPTextModelOutput, config_class=CLIPTextConfig
|
| 1110 |
+
)
|
| 1111 |
+
|
| 1112 |
+
|
| 1113 |
+
class FlaxCLIPVisionModule(nn.Module):
|
| 1114 |
+
config: CLIPVisionConfig
|
| 1115 |
+
dtype: jnp.dtype = jnp.float32
|
| 1116 |
+
|
| 1117 |
+
def setup(self):
|
| 1118 |
+
self.vision_model = FlaxCLIPVisionTransformer(self.config, dtype=self.dtype)
|
| 1119 |
+
|
| 1120 |
+
def __call__(
|
| 1121 |
+
self,
|
| 1122 |
+
pixel_values,
|
| 1123 |
+
deterministic: bool = True,
|
| 1124 |
+
output_attentions: bool = False,
|
| 1125 |
+
output_hidden_states: bool = False,
|
| 1126 |
+
return_dict: bool = True,
|
| 1127 |
+
):
|
| 1128 |
+
return self.vision_model(
|
| 1129 |
+
pixel_values=pixel_values,
|
| 1130 |
+
deterministic=deterministic,
|
| 1131 |
+
output_attentions=output_attentions,
|
| 1132 |
+
output_hidden_states=output_hidden_states,
|
| 1133 |
+
return_dict=return_dict,
|
| 1134 |
+
)
|
| 1135 |
+
|
| 1136 |
+
|
| 1137 |
+
class FlaxCLIPVisionModel(FlaxCLIPVisionPreTrainedModel):
|
| 1138 |
+
module_class = FlaxCLIPVisionModule
|
| 1139 |
+
|
| 1140 |
+
|
| 1141 |
+
FLAX_CLIP_VISION_MODEL_DOCSTRING = """
|
| 1142 |
+
Returns:
|
| 1143 |
+
|
| 1144 |
+
Example:
|
| 1145 |
+
|
| 1146 |
+
```python
|
| 1147 |
+
>>> from PIL import Image
|
| 1148 |
+
>>> import requests
|
| 1149 |
+
>>> from transformers import AutoProcessor, FlaxCLIPVisionModel
|
| 1150 |
+
|
| 1151 |
+
>>> model = FlaxCLIPVisionModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1152 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1153 |
+
|
| 1154 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1155 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1156 |
+
|
| 1157 |
+
>>> inputs = processor(images=image, return_tensors="np")
|
| 1158 |
+
|
| 1159 |
+
>>> outputs = model(**inputs)
|
| 1160 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 1161 |
+
>>> pooler_output = outputs.pooler_output # pooled CLS states
|
| 1162 |
+
```
|
| 1163 |
+
"""
|
| 1164 |
+
|
| 1165 |
+
overwrite_call_docstring(FlaxCLIPVisionModel, CLIP_VISION_INPUTS_DOCSTRING + FLAX_CLIP_VISION_MODEL_DOCSTRING)
|
| 1166 |
+
append_replace_return_docstrings(
|
| 1167 |
+
FlaxCLIPVisionModel, output_type=FlaxBaseModelOutputWithPooling, config_class=CLIPVisionConfig
|
| 1168 |
+
)
|
| 1169 |
+
|
| 1170 |
+
|
| 1171 |
+
class FlaxCLIPModule(nn.Module):
|
| 1172 |
+
config: CLIPConfig
|
| 1173 |
+
dtype: jnp.dtype = jnp.float32
|
| 1174 |
+
|
| 1175 |
+
def setup(self):
|
| 1176 |
+
text_config = self.config.text_config
|
| 1177 |
+
vision_config = self.config.vision_config
|
| 1178 |
+
|
| 1179 |
+
self.projection_dim = self.config.projection_dim
|
| 1180 |
+
self.text_embed_dim = text_config.hidden_size
|
| 1181 |
+
self.vision_embed_dim = vision_config.hidden_size
|
| 1182 |
+
|
| 1183 |
+
self.text_model = FlaxCLIPTextTransformer(text_config, dtype=self.dtype)
|
| 1184 |
+
self.vision_model = FlaxCLIPVisionTransformer(vision_config, dtype=self.dtype)
|
| 1185 |
+
|
| 1186 |
+
self.visual_projection = nn.Dense(
|
| 1187 |
+
self.projection_dim,
|
| 1188 |
+
dtype=self.dtype,
|
| 1189 |
+
kernel_init=jax.nn.initializers.normal(0.02),
|
| 1190 |
+
use_bias=False,
|
| 1191 |
+
)
|
| 1192 |
+
self.text_projection = nn.Dense(
|
| 1193 |
+
self.projection_dim,
|
| 1194 |
+
dtype=self.dtype,
|
| 1195 |
+
kernel_init=jax.nn.initializers.normal(0.02),
|
| 1196 |
+
use_bias=False,
|
| 1197 |
+
)
|
| 1198 |
+
|
| 1199 |
+
self.logit_scale = self.param(
|
| 1200 |
+
"logit_scale", lambda _, shape: jnp.ones(shape) * self.config.logit_scale_init_value, []
|
| 1201 |
+
)
|
| 1202 |
+
|
| 1203 |
+
def __call__(
|
| 1204 |
+
self,
|
| 1205 |
+
input_ids=None,
|
| 1206 |
+
pixel_values=None,
|
| 1207 |
+
attention_mask=None,
|
| 1208 |
+
position_ids=None,
|
| 1209 |
+
deterministic: bool = True,
|
| 1210 |
+
output_attentions=None,
|
| 1211 |
+
output_hidden_states=None,
|
| 1212 |
+
return_dict=None,
|
| 1213 |
+
):
|
| 1214 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1215 |
+
|
| 1216 |
+
vision_outputs = self.vision_model(
|
| 1217 |
+
pixel_values=pixel_values,
|
| 1218 |
+
deterministic=deterministic,
|
| 1219 |
+
output_attentions=output_attentions,
|
| 1220 |
+
output_hidden_states=output_hidden_states,
|
| 1221 |
+
return_dict=return_dict,
|
| 1222 |
+
)
|
| 1223 |
+
|
| 1224 |
+
text_outputs = self.text_model(
|
| 1225 |
+
input_ids=input_ids,
|
| 1226 |
+
attention_mask=attention_mask,
|
| 1227 |
+
position_ids=position_ids,
|
| 1228 |
+
deterministic=deterministic,
|
| 1229 |
+
output_attentions=output_attentions,
|
| 1230 |
+
output_hidden_states=output_hidden_states,
|
| 1231 |
+
return_dict=return_dict,
|
| 1232 |
+
)
|
| 1233 |
+
|
| 1234 |
+
image_embeds = vision_outputs[1]
|
| 1235 |
+
image_embeds = self.visual_projection(image_embeds)
|
| 1236 |
+
|
| 1237 |
+
text_embeds = text_outputs[1]
|
| 1238 |
+
text_embeds = self.text_projection(text_embeds)
|
| 1239 |
+
|
| 1240 |
+
# normalized features
|
| 1241 |
+
image_embeds = image_embeds / jnp.linalg.norm(image_embeds, axis=-1, keepdims=True)
|
| 1242 |
+
text_embeds = text_embeds / jnp.linalg.norm(text_embeds, axis=-1, keepdims=True)
|
| 1243 |
+
|
| 1244 |
+
# cosine similarity as logits
|
| 1245 |
+
logit_scale = jnp.exp(self.logit_scale)
|
| 1246 |
+
logits_per_text = jnp.matmul(text_embeds, image_embeds.T) * logit_scale
|
| 1247 |
+
logits_per_image = logits_per_text.T
|
| 1248 |
+
|
| 1249 |
+
if not return_dict:
|
| 1250 |
+
return (logits_per_image, logits_per_text, text_embeds, image_embeds, text_outputs, vision_outputs)
|
| 1251 |
+
|
| 1252 |
+
return FlaxCLIPOutput(
|
| 1253 |
+
logits_per_image=logits_per_image,
|
| 1254 |
+
logits_per_text=logits_per_text,
|
| 1255 |
+
text_embeds=text_embeds,
|
| 1256 |
+
image_embeds=image_embeds,
|
| 1257 |
+
text_model_output=text_outputs,
|
| 1258 |
+
vision_model_output=vision_outputs,
|
| 1259 |
+
)
|
| 1260 |
+
|
| 1261 |
+
|
| 1262 |
+
@add_start_docstrings(CLIP_START_DOCSTRING)
|
| 1263 |
+
class FlaxCLIPModel(FlaxCLIPPreTrainedModel):
|
| 1264 |
+
module_class = FlaxCLIPModule
|
| 1265 |
+
|
| 1266 |
+
|
| 1267 |
+
FLAX_CLIP_MODEL_DOCSTRING = """
|
| 1268 |
+
Returns:
|
| 1269 |
+
|
| 1270 |
+
Example:
|
| 1271 |
+
|
| 1272 |
+
```python
|
| 1273 |
+
>>> import jax
|
| 1274 |
+
>>> from PIL import Image
|
| 1275 |
+
>>> import requests
|
| 1276 |
+
>>> from transformers import AutoProcessor, FlaxCLIPModel
|
| 1277 |
+
|
| 1278 |
+
>>> model = FlaxCLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1279 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1280 |
+
|
| 1281 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1282 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1283 |
+
|
| 1284 |
+
>>> inputs = processor(
|
| 1285 |
+
... text=["a photo of a cat", "a photo of a dog"], images=image, return_tensors="np", padding=True
|
| 1286 |
+
... )
|
| 1287 |
+
|
| 1288 |
+
>>> outputs = model(**inputs)
|
| 1289 |
+
>>> logits_per_image = outputs.logits_per_image # this is the image-text similarity score
|
| 1290 |
+
>>> probs = jax.nn.softmax(logits_per_image, axis=1) # we can take the softmax to get the label probabilities
|
| 1291 |
+
```
|
| 1292 |
+
"""
|
| 1293 |
+
|
| 1294 |
+
overwrite_call_docstring(FlaxCLIPModel, CLIP_INPUTS_DOCSTRING + FLAX_CLIP_MODEL_DOCSTRING)
|
| 1295 |
+
append_replace_return_docstrings(FlaxCLIPModel, output_type=FlaxCLIPOutput, config_class=CLIPConfig)
|
| 1296 |
+
|
| 1297 |
+
|
| 1298 |
+
__all__ = [
|
| 1299 |
+
"FlaxCLIPModel",
|
| 1300 |
+
"FlaxCLIPPreTrainedModel",
|
| 1301 |
+
"FlaxCLIPTextModel",
|
| 1302 |
+
"FlaxCLIPTextPreTrainedModel",
|
| 1303 |
+
"FlaxCLIPTextModelWithProjection",
|
| 1304 |
+
"FlaxCLIPVisionModel",
|
| 1305 |
+
"FlaxCLIPVisionPreTrainedModel",
|
| 1306 |
+
]
|
lib/python3.12/site-packages/transformers/models/clip/modeling_tf_clip.py
ADDED
|
@@ -0,0 +1,1460 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2021 The OpenAI Team Authors and The HuggingFace Team. All rights reserved.
|
| 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 |
+
"""TF 2.0 CLIP model."""
|
| 16 |
+
|
| 17 |
+
from __future__ import annotations
|
| 18 |
+
|
| 19 |
+
import math
|
| 20 |
+
from dataclasses import dataclass
|
| 21 |
+
from typing import Any, Optional, Tuple, Union
|
| 22 |
+
|
| 23 |
+
import numpy as np
|
| 24 |
+
import tensorflow as tf
|
| 25 |
+
|
| 26 |
+
from ...activations_tf import get_tf_activation
|
| 27 |
+
from ...modeling_tf_outputs import TFBaseModelOutput, TFBaseModelOutputWithPooling
|
| 28 |
+
|
| 29 |
+
# Public API
|
| 30 |
+
from ...modeling_tf_utils import (
|
| 31 |
+
TFModelInputType,
|
| 32 |
+
TFPreTrainedModel,
|
| 33 |
+
get_initializer,
|
| 34 |
+
keras,
|
| 35 |
+
keras_serializable,
|
| 36 |
+
unpack_inputs,
|
| 37 |
+
)
|
| 38 |
+
from ...tf_utils import check_embeddings_within_bounds, shape_list, stable_softmax
|
| 39 |
+
from ...utils import (
|
| 40 |
+
ModelOutput,
|
| 41 |
+
add_start_docstrings,
|
| 42 |
+
add_start_docstrings_to_model_forward,
|
| 43 |
+
logging,
|
| 44 |
+
replace_return_docstrings,
|
| 45 |
+
)
|
| 46 |
+
from .configuration_clip import CLIPConfig, CLIPTextConfig, CLIPVisionConfig
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
logger = logging.get_logger(__name__)
|
| 50 |
+
|
| 51 |
+
_CHECKPOINT_FOR_DOC = "openai/clip-vit-base-patch32"
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
LARGE_NEGATIVE = -1e8
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
# Copied from transformers.models.bart.modeling_tf_bart._expand_mask
|
| 58 |
+
def _expand_mask(mask: tf.Tensor, tgt_len: Optional[int] = None):
|
| 59 |
+
"""
|
| 60 |
+
Expands attention_mask from `[bsz, seq_len]` to `[bsz, 1, tgt_seq_len, src_seq_len]`.
|
| 61 |
+
"""
|
| 62 |
+
src_len = shape_list(mask)[1]
|
| 63 |
+
tgt_len = tgt_len if tgt_len is not None else src_len
|
| 64 |
+
one_cst = tf.constant(1.0)
|
| 65 |
+
mask = tf.cast(mask, dtype=one_cst.dtype)
|
| 66 |
+
expanded_mask = tf.tile(mask[:, None, None, :], (1, 1, tgt_len, 1))
|
| 67 |
+
|
| 68 |
+
return (one_cst - expanded_mask) * LARGE_NEGATIVE
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
# contrastive loss function, adapted from
|
| 72 |
+
# https://sachinruk.github.io/blog/pytorch/pytorch%20lightning/loss%20function/gpu/2021/03/07/CLIP.html
|
| 73 |
+
def contrastive_loss(logits: tf.Tensor) -> tf.Tensor:
|
| 74 |
+
return tf.math.reduce_mean(
|
| 75 |
+
keras.metrics.sparse_categorical_crossentropy(
|
| 76 |
+
y_true=tf.range(shape_list(logits)[0]), y_pred=logits, from_logits=True
|
| 77 |
+
)
|
| 78 |
+
)
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def clip_loss(similarity: tf.Tensor) -> tf.Tensor:
|
| 82 |
+
caption_loss = contrastive_loss(similarity)
|
| 83 |
+
image_loss = contrastive_loss(tf.transpose(similarity))
|
| 84 |
+
return (caption_loss + image_loss) / 2.0
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
@dataclass
|
| 88 |
+
class TFCLIPOutput(ModelOutput):
|
| 89 |
+
"""
|
| 90 |
+
Args:
|
| 91 |
+
loss (`tf.Tensor` of shape `(1,)`, *optional*, returned when `return_loss` is `True`):
|
| 92 |
+
Contrastive loss for image-text similarity.
|
| 93 |
+
logits_per_image:(`tf.Tensor` of shape `(image_batch_size, text_batch_size)`):
|
| 94 |
+
The scaled dot product scores between `image_embeds` and `text_embeds`. This represents the image-text
|
| 95 |
+
similarity scores.
|
| 96 |
+
logits_per_text:(`tf.Tensor` of shape `(text_batch_size, image_batch_size)`):
|
| 97 |
+
The scaled dot product scores between `text_embeds` and `image_embeds`. This represents the text-image
|
| 98 |
+
similarity scores.
|
| 99 |
+
text_embeds(`tf.Tensor` of shape `(batch_size, output_dim`):
|
| 100 |
+
The text embeddings obtained by applying the projection layer to the pooled output of [`TFCLIPTextModel`].
|
| 101 |
+
image_embeds(`tf.Tensor` of shape `(batch_size, output_dim`):
|
| 102 |
+
The image embeddings obtained by applying the projection layer to the pooled output of
|
| 103 |
+
[`TFCLIPVisionModel`].
|
| 104 |
+
text_model_output([`~modeling_tf_utils.TFBaseModelOutputWithPooling`]):
|
| 105 |
+
The output of the [`TFCLIPTextModel`].
|
| 106 |
+
vision_model_output([`~modeling_tf_utils.TFBaseModelOutputWithPooling`]):
|
| 107 |
+
The output of the [`TFCLIPVisionModel`].
|
| 108 |
+
"""
|
| 109 |
+
|
| 110 |
+
loss: tf.Tensor | None = None
|
| 111 |
+
logits_per_image: Optional[tf.Tensor] = None
|
| 112 |
+
logits_per_text: Optional[tf.Tensor] = None
|
| 113 |
+
text_embeds: Optional[tf.Tensor] = None
|
| 114 |
+
image_embeds: Optional[tf.Tensor] = None
|
| 115 |
+
text_model_output: TFBaseModelOutputWithPooling = None
|
| 116 |
+
vision_model_output: TFBaseModelOutputWithPooling = None
|
| 117 |
+
|
| 118 |
+
def to_tuple(self) -> Tuple[Any]:
|
| 119 |
+
return tuple(
|
| 120 |
+
self[k] if k not in ["text_model_output", "vision_model_output"] else getattr(self, k).to_tuple()
|
| 121 |
+
for k in self.keys()
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
class TFCLIPVisionEmbeddings(keras.layers.Layer):
|
| 126 |
+
def __init__(self, config: CLIPVisionConfig, **kwargs):
|
| 127 |
+
super().__init__(**kwargs)
|
| 128 |
+
|
| 129 |
+
self.embed_dim = config.hidden_size
|
| 130 |
+
self.image_size = config.image_size
|
| 131 |
+
self.patch_size = config.patch_size
|
| 132 |
+
|
| 133 |
+
self.num_patches = (self.image_size // self.patch_size) ** 2
|
| 134 |
+
self.num_positions = self.num_patches + 1
|
| 135 |
+
|
| 136 |
+
self.config = config
|
| 137 |
+
|
| 138 |
+
self.patch_embedding = keras.layers.Conv2D(
|
| 139 |
+
filters=self.embed_dim,
|
| 140 |
+
kernel_size=self.patch_size,
|
| 141 |
+
strides=self.patch_size,
|
| 142 |
+
padding="valid",
|
| 143 |
+
data_format="channels_last",
|
| 144 |
+
use_bias=False,
|
| 145 |
+
kernel_initializer=get_initializer(self.config.initializer_range * self.config.initializer_factor),
|
| 146 |
+
name="patch_embedding",
|
| 147 |
+
)
|
| 148 |
+
|
| 149 |
+
def build(self, input_shape: tf.TensorShape = None):
|
| 150 |
+
factor = self.config.initializer_factor
|
| 151 |
+
|
| 152 |
+
self.class_embedding = self.add_weight(
|
| 153 |
+
shape=(self.embed_dim,),
|
| 154 |
+
initializer=get_initializer(self.embed_dim**-0.5 * factor),
|
| 155 |
+
trainable=True,
|
| 156 |
+
name="class_embedding",
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
with tf.name_scope("position_embedding"):
|
| 160 |
+
self.position_embedding = self.add_weight(
|
| 161 |
+
shape=(self.num_positions, self.embed_dim),
|
| 162 |
+
initializer=get_initializer(self.config.initializer_range * factor),
|
| 163 |
+
trainable=True,
|
| 164 |
+
name="embeddings",
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
if self.built:
|
| 168 |
+
return
|
| 169 |
+
self.built = True
|
| 170 |
+
if getattr(self, "patch_embedding", None) is not None:
|
| 171 |
+
with tf.name_scope(self.patch_embedding.name):
|
| 172 |
+
self.patch_embedding.build([None, None, None, self.config.num_channels])
|
| 173 |
+
|
| 174 |
+
def call(self, pixel_values: tf.Tensor) -> tf.Tensor:
|
| 175 |
+
"""`pixel_values` is expected to be of NCHW format."""
|
| 176 |
+
|
| 177 |
+
batch_size, num_channels, height, width = shape_list(pixel_values)
|
| 178 |
+
|
| 179 |
+
# When running on CPU, `tf.nn.conv2d` doesn't support `NCHW` format.
|
| 180 |
+
# So change the input format from `NCHW` to `NHWC`.
|
| 181 |
+
# shape = (batch_size, in_height, in_width, in_channels=num_channels)
|
| 182 |
+
pixel_values = tf.transpose(pixel_values, perm=(0, 2, 3, 1))
|
| 183 |
+
|
| 184 |
+
patch_embeds = self.patch_embedding(pixel_values)
|
| 185 |
+
|
| 186 |
+
# Change the 2D spatial dimensions to a single temporal dimension.
|
| 187 |
+
# shape = (batch_size, num_patches, out_channels=embed_dim)
|
| 188 |
+
patch_embeds = tf.reshape(tensor=patch_embeds, shape=(batch_size, self.num_patches, -1))
|
| 189 |
+
|
| 190 |
+
# add the [CLS] token to the embedded patch tokens
|
| 191 |
+
class_embeds = tf.broadcast_to(self.class_embedding, shape=(batch_size, 1, self.embed_dim))
|
| 192 |
+
embeddings = tf.concat((class_embeds, patch_embeds), axis=1)
|
| 193 |
+
|
| 194 |
+
embeddings = embeddings + self.position_embedding
|
| 195 |
+
|
| 196 |
+
return embeddings
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
class TFCLIPTextEmbeddings(keras.layers.Layer):
|
| 200 |
+
def __init__(self, config: CLIPTextConfig, **kwargs):
|
| 201 |
+
super().__init__(**kwargs)
|
| 202 |
+
|
| 203 |
+
self.embed_dim = config.hidden_size
|
| 204 |
+
|
| 205 |
+
self.config = config
|
| 206 |
+
|
| 207 |
+
def build(self, input_shape: tf.TensorShape = None):
|
| 208 |
+
with tf.name_scope("token_embedding"):
|
| 209 |
+
self.weight = self.add_weight(
|
| 210 |
+
shape=(self.config.vocab_size, self.embed_dim),
|
| 211 |
+
initializer=get_initializer(self.config.initializer_factor * self.config.initializer_range),
|
| 212 |
+
trainable=True,
|
| 213 |
+
name="weight",
|
| 214 |
+
)
|
| 215 |
+
|
| 216 |
+
with tf.name_scope("position_embedding"):
|
| 217 |
+
self.position_embedding = self.add_weight(
|
| 218 |
+
shape=(self.config.max_position_embeddings, self.embed_dim),
|
| 219 |
+
initializer=get_initializer(self.config.initializer_factor * self.config.initializer_range),
|
| 220 |
+
trainable=True,
|
| 221 |
+
name="embeddings",
|
| 222 |
+
)
|
| 223 |
+
|
| 224 |
+
super().build(input_shape)
|
| 225 |
+
|
| 226 |
+
def call(
|
| 227 |
+
self,
|
| 228 |
+
input_ids: Optional[tf.Tensor] = None,
|
| 229 |
+
position_ids: Optional[tf.Tensor] = None,
|
| 230 |
+
inputs_embeds: Optional[tf.Tensor] = None,
|
| 231 |
+
) -> tf.Tensor:
|
| 232 |
+
"""
|
| 233 |
+
Applies embedding based on inputs tensor.
|
| 234 |
+
|
| 235 |
+
Returns:
|
| 236 |
+
final_embeddings (`tf.Tensor`): output embedding tensor.
|
| 237 |
+
"""
|
| 238 |
+
if input_ids is None and inputs_embeds is None:
|
| 239 |
+
raise ValueError("You have to specify either input_ids or inputs_embeds")
|
| 240 |
+
|
| 241 |
+
if inputs_embeds is None:
|
| 242 |
+
check_embeddings_within_bounds(input_ids, self.config.vocab_size)
|
| 243 |
+
inputs_embeds = tf.gather(params=self.weight, indices=input_ids)
|
| 244 |
+
|
| 245 |
+
input_shape = shape_list(inputs_embeds)[:-1]
|
| 246 |
+
|
| 247 |
+
if position_ids is None:
|
| 248 |
+
position_ids = tf.expand_dims(tf.range(start=0, limit=input_shape[-1]), axis=0)
|
| 249 |
+
|
| 250 |
+
position_embeds = tf.gather(params=self.position_embedding, indices=position_ids)
|
| 251 |
+
position_embeds = tf.tile(input=position_embeds, multiples=(input_shape[0], 1, 1))
|
| 252 |
+
final_embeddings = inputs_embeds + position_embeds
|
| 253 |
+
|
| 254 |
+
return final_embeddings
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
class TFCLIPAttention(keras.layers.Layer):
|
| 258 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 259 |
+
|
| 260 |
+
def __init__(self, config: CLIPConfig, **kwargs):
|
| 261 |
+
super().__init__(**kwargs)
|
| 262 |
+
|
| 263 |
+
self.embed_dim = config.hidden_size
|
| 264 |
+
self.num_attention_heads = config.num_attention_heads
|
| 265 |
+
self.attention_head_size = self.embed_dim // self.num_attention_heads
|
| 266 |
+
if self.attention_head_size * self.num_attention_heads != self.embed_dim:
|
| 267 |
+
raise ValueError(
|
| 268 |
+
f"embed_dim must be divisible by num_heads (got `embed_dim`: {self.embed_dim} and `num_heads`:"
|
| 269 |
+
f" {self.num_attention_heads})."
|
| 270 |
+
)
|
| 271 |
+
|
| 272 |
+
factor = config.initializer_factor
|
| 273 |
+
in_proj_std = (self.embed_dim**-0.5) * ((2 * config.num_hidden_layers) ** -0.5) * factor
|
| 274 |
+
out_proj_std = (self.embed_dim**-0.5) * factor
|
| 275 |
+
|
| 276 |
+
self.sqrt_att_head_size = math.sqrt(self.attention_head_size)
|
| 277 |
+
|
| 278 |
+
self.q_proj = keras.layers.Dense(
|
| 279 |
+
units=self.embed_dim, kernel_initializer=get_initializer(in_proj_std), name="q_proj"
|
| 280 |
+
)
|
| 281 |
+
self.k_proj = keras.layers.Dense(
|
| 282 |
+
units=self.embed_dim, kernel_initializer=get_initializer(in_proj_std), name="k_proj"
|
| 283 |
+
)
|
| 284 |
+
self.v_proj = keras.layers.Dense(
|
| 285 |
+
units=self.embed_dim, kernel_initializer=get_initializer(in_proj_std), name="v_proj"
|
| 286 |
+
)
|
| 287 |
+
|
| 288 |
+
self.dropout = keras.layers.Dropout(rate=config.attention_dropout)
|
| 289 |
+
|
| 290 |
+
self.out_proj = keras.layers.Dense(
|
| 291 |
+
units=self.embed_dim, kernel_initializer=get_initializer(out_proj_std), name="out_proj"
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
+
# copied from transformers.models.bert.modeling_tf_bert.TFBertSelfAttention.transpose_for_scores
|
| 295 |
+
def transpose_for_scores(self, tensor: tf.Tensor, batch_size: int) -> tf.Tensor:
|
| 296 |
+
# Reshape from [batch_size, seq_length, all_head_size] to [batch_size, seq_length, num_attention_heads, attention_head_size]
|
| 297 |
+
tensor = tf.reshape(tensor=tensor, shape=(batch_size, -1, self.num_attention_heads, self.attention_head_size))
|
| 298 |
+
|
| 299 |
+
# Transpose the tensor from [batch_size, seq_length, num_attention_heads, attention_head_size] to [batch_size, num_attention_heads, seq_length, attention_head_size]
|
| 300 |
+
return tf.transpose(tensor, perm=[0, 2, 1, 3])
|
| 301 |
+
|
| 302 |
+
def call(
|
| 303 |
+
self,
|
| 304 |
+
hidden_states: tf.Tensor,
|
| 305 |
+
attention_mask: tf.Tensor,
|
| 306 |
+
causal_attention_mask: tf.Tensor,
|
| 307 |
+
output_attentions: bool,
|
| 308 |
+
training: bool = False,
|
| 309 |
+
) -> Tuple[tf.Tensor]:
|
| 310 |
+
"""Input shape: Batch x Time x Channel"""
|
| 311 |
+
|
| 312 |
+
batch_size = shape_list(hidden_states)[0]
|
| 313 |
+
mixed_query_layer = self.q_proj(inputs=hidden_states)
|
| 314 |
+
mixed_key_layer = self.k_proj(inputs=hidden_states)
|
| 315 |
+
mixed_value_layer = self.v_proj(inputs=hidden_states)
|
| 316 |
+
query_layer = self.transpose_for_scores(mixed_query_layer, batch_size)
|
| 317 |
+
key_layer = self.transpose_for_scores(mixed_key_layer, batch_size)
|
| 318 |
+
value_layer = self.transpose_for_scores(mixed_value_layer, batch_size)
|
| 319 |
+
|
| 320 |
+
# Take the dot product between "query" and "key" to get the raw attention scores.
|
| 321 |
+
# (batch size, num_heads, seq_len_q, seq_len_k)
|
| 322 |
+
attention_scores = tf.matmul(query_layer, key_layer, transpose_b=True)
|
| 323 |
+
dk = tf.cast(self.sqrt_att_head_size, dtype=attention_scores.dtype)
|
| 324 |
+
attention_scores = tf.divide(attention_scores, dk)
|
| 325 |
+
|
| 326 |
+
# apply the causal_attention_mask first
|
| 327 |
+
if causal_attention_mask is not None:
|
| 328 |
+
# Apply the causal attention mask (precomputed for all layers in TFCLIPModel call() function)
|
| 329 |
+
attention_scores = tf.add(attention_scores, causal_attention_mask)
|
| 330 |
+
|
| 331 |
+
if attention_mask is not None:
|
| 332 |
+
# Apply the attention mask (precomputed for all layers in TFCLIPModel call() function)
|
| 333 |
+
attention_scores = tf.add(attention_scores, attention_mask)
|
| 334 |
+
|
| 335 |
+
# Normalize the attention scores to probabilities.
|
| 336 |
+
_attention_probs = stable_softmax(logits=attention_scores, axis=-1)
|
| 337 |
+
|
| 338 |
+
# This is actually dropping out entire tokens to attend to, which might
|
| 339 |
+
# seem a bit unusual, but is taken from the original Transformer paper.
|
| 340 |
+
attention_probs = self.dropout(inputs=_attention_probs, training=training)
|
| 341 |
+
|
| 342 |
+
attention_output = tf.matmul(attention_probs, value_layer)
|
| 343 |
+
attention_output = tf.transpose(attention_output, perm=[0, 2, 1, 3])
|
| 344 |
+
|
| 345 |
+
# (batch_size, seq_len_q, embed_dim)
|
| 346 |
+
attention_output = tf.reshape(tensor=attention_output, shape=(batch_size, -1, self.embed_dim))
|
| 347 |
+
|
| 348 |
+
attention_output = self.out_proj(attention_output, training=training)
|
| 349 |
+
# In TFBert, attention weights are returned after dropout.
|
| 350 |
+
# However, in CLIP, they are returned before dropout.
|
| 351 |
+
outputs = (attention_output, _attention_probs) if output_attentions else (attention_output,)
|
| 352 |
+
|
| 353 |
+
return outputs
|
| 354 |
+
|
| 355 |
+
def build(self, input_shape=None):
|
| 356 |
+
if self.built:
|
| 357 |
+
return
|
| 358 |
+
self.built = True
|
| 359 |
+
if getattr(self, "q_proj", None) is not None:
|
| 360 |
+
with tf.name_scope(self.q_proj.name):
|
| 361 |
+
self.q_proj.build([None, None, self.embed_dim])
|
| 362 |
+
if getattr(self, "k_proj", None) is not None:
|
| 363 |
+
with tf.name_scope(self.k_proj.name):
|
| 364 |
+
self.k_proj.build([None, None, self.embed_dim])
|
| 365 |
+
if getattr(self, "v_proj", None) is not None:
|
| 366 |
+
with tf.name_scope(self.v_proj.name):
|
| 367 |
+
self.v_proj.build([None, None, self.embed_dim])
|
| 368 |
+
if getattr(self, "out_proj", None) is not None:
|
| 369 |
+
with tf.name_scope(self.out_proj.name):
|
| 370 |
+
self.out_proj.build([None, None, self.embed_dim])
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
class TFCLIPMLP(keras.layers.Layer):
|
| 374 |
+
def __init__(self, config: CLIPConfig, **kwargs):
|
| 375 |
+
super().__init__(**kwargs)
|
| 376 |
+
|
| 377 |
+
self.activation_fn = get_tf_activation(config.hidden_act)
|
| 378 |
+
|
| 379 |
+
factor = config.initializer_factor
|
| 380 |
+
in_proj_std = (config.hidden_size**-0.5) * ((2 * config.num_hidden_layers) ** -0.5) * factor
|
| 381 |
+
fc_std = (2 * config.hidden_size) ** -0.5 * factor
|
| 382 |
+
|
| 383 |
+
self.fc1 = keras.layers.Dense(
|
| 384 |
+
units=config.intermediate_size, kernel_initializer=get_initializer(fc_std), name="fc1"
|
| 385 |
+
)
|
| 386 |
+
self.fc2 = keras.layers.Dense(
|
| 387 |
+
units=config.hidden_size, kernel_initializer=get_initializer(in_proj_std), name="fc2"
|
| 388 |
+
)
|
| 389 |
+
self.config = config
|
| 390 |
+
|
| 391 |
+
def call(self, hidden_states: tf.Tensor) -> tf.Tensor:
|
| 392 |
+
hidden_states = self.fc1(inputs=hidden_states)
|
| 393 |
+
hidden_states = self.activation_fn(hidden_states)
|
| 394 |
+
hidden_states = self.fc2(inputs=hidden_states)
|
| 395 |
+
return hidden_states
|
| 396 |
+
|
| 397 |
+
def build(self, input_shape=None):
|
| 398 |
+
if self.built:
|
| 399 |
+
return
|
| 400 |
+
self.built = True
|
| 401 |
+
if getattr(self, "fc1", None) is not None:
|
| 402 |
+
with tf.name_scope(self.fc1.name):
|
| 403 |
+
self.fc1.build([None, None, self.config.hidden_size])
|
| 404 |
+
if getattr(self, "fc2", None) is not None:
|
| 405 |
+
with tf.name_scope(self.fc2.name):
|
| 406 |
+
self.fc2.build([None, None, self.config.intermediate_size])
|
| 407 |
+
|
| 408 |
+
|
| 409 |
+
class TFCLIPEncoderLayer(keras.layers.Layer):
|
| 410 |
+
def __init__(self, config: CLIPConfig, **kwargs):
|
| 411 |
+
super().__init__(**kwargs)
|
| 412 |
+
|
| 413 |
+
self.embed_dim = config.hidden_size
|
| 414 |
+
self.self_attn = TFCLIPAttention(config, name="self_attn")
|
| 415 |
+
self.layer_norm1 = keras.layers.LayerNormalization(epsilon=config.layer_norm_eps, name="layer_norm1")
|
| 416 |
+
self.mlp = TFCLIPMLP(config, name="mlp")
|
| 417 |
+
self.layer_norm2 = keras.layers.LayerNormalization(epsilon=config.layer_norm_eps, name="layer_norm2")
|
| 418 |
+
|
| 419 |
+
def call(
|
| 420 |
+
self,
|
| 421 |
+
hidden_states: tf.Tensor,
|
| 422 |
+
attention_mask: tf.Tensor,
|
| 423 |
+
causal_attention_mask: tf.Tensor,
|
| 424 |
+
output_attentions: bool,
|
| 425 |
+
training: bool = False,
|
| 426 |
+
) -> Tuple[tf.Tensor]:
|
| 427 |
+
"""
|
| 428 |
+
Args:
|
| 429 |
+
hidden_states (`tf.Tensor`): input to the layer of shape `(batch, seq_len, embed_dim)`
|
| 430 |
+
attention_mask (`tf.Tensor`): attention mask of size
|
| 431 |
+
`(batch, 1, tgt_len, src_len)` where padding elements are indicated by very large negative values.
|
| 432 |
+
causal_attention_mask (`tf.Tensor`): causal attention mask of size
|
| 433 |
+
`(batch, 1, tgt_len, src_len)` where padding elements are indicated by very large negative values.
|
| 434 |
+
output_attentions (`bool`):
|
| 435 |
+
Whether or not to return the attentions tensors of all attention layers. See `outputs` under returned
|
| 436 |
+
tensors for more detail.
|
| 437 |
+
"""
|
| 438 |
+
residual = hidden_states
|
| 439 |
+
|
| 440 |
+
hidden_states = self.layer_norm1(inputs=hidden_states)
|
| 441 |
+
attention_outputs = self.self_attn(
|
| 442 |
+
hidden_states=hidden_states,
|
| 443 |
+
attention_mask=attention_mask,
|
| 444 |
+
causal_attention_mask=causal_attention_mask,
|
| 445 |
+
output_attentions=output_attentions,
|
| 446 |
+
training=training,
|
| 447 |
+
)
|
| 448 |
+
hidden_states = attention_outputs[0]
|
| 449 |
+
hidden_states = residual + hidden_states
|
| 450 |
+
|
| 451 |
+
residual = hidden_states
|
| 452 |
+
hidden_states = self.layer_norm2(inputs=hidden_states)
|
| 453 |
+
hidden_states = self.mlp(hidden_states=hidden_states)
|
| 454 |
+
hidden_states = residual + hidden_states
|
| 455 |
+
|
| 456 |
+
outputs = (hidden_states,) + attention_outputs[1:] # add attentions if we output them
|
| 457 |
+
|
| 458 |
+
return outputs
|
| 459 |
+
|
| 460 |
+
def build(self, input_shape=None):
|
| 461 |
+
if self.built:
|
| 462 |
+
return
|
| 463 |
+
self.built = True
|
| 464 |
+
if getattr(self, "self_attn", None) is not None:
|
| 465 |
+
with tf.name_scope(self.self_attn.name):
|
| 466 |
+
self.self_attn.build(None)
|
| 467 |
+
if getattr(self, "layer_norm1", None) is not None:
|
| 468 |
+
with tf.name_scope(self.layer_norm1.name):
|
| 469 |
+
self.layer_norm1.build([None, None, self.embed_dim])
|
| 470 |
+
if getattr(self, "mlp", None) is not None:
|
| 471 |
+
with tf.name_scope(self.mlp.name):
|
| 472 |
+
self.mlp.build(None)
|
| 473 |
+
if getattr(self, "layer_norm2", None) is not None:
|
| 474 |
+
with tf.name_scope(self.layer_norm2.name):
|
| 475 |
+
self.layer_norm2.build([None, None, self.embed_dim])
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
class TFCLIPEncoder(keras.layers.Layer):
|
| 479 |
+
"""
|
| 480 |
+
Transformer encoder consisting of `config.num_hidden_layers` self attention layers. Each layer is a
|
| 481 |
+
[`TFCLIPEncoderLayer`].
|
| 482 |
+
|
| 483 |
+
Args:
|
| 484 |
+
config: CLIPConfig
|
| 485 |
+
"""
|
| 486 |
+
|
| 487 |
+
def __init__(self, config: CLIPConfig, **kwargs):
|
| 488 |
+
super().__init__(**kwargs)
|
| 489 |
+
|
| 490 |
+
self.layers = [TFCLIPEncoderLayer(config, name=f"layers_._{i}") for i in range(config.num_hidden_layers)]
|
| 491 |
+
|
| 492 |
+
def call(
|
| 493 |
+
self,
|
| 494 |
+
hidden_states: tf.Tensor,
|
| 495 |
+
attention_mask: tf.Tensor,
|
| 496 |
+
causal_attention_mask: tf.Tensor,
|
| 497 |
+
output_attentions: bool,
|
| 498 |
+
output_hidden_states: bool,
|
| 499 |
+
return_dict: bool,
|
| 500 |
+
training: bool = False,
|
| 501 |
+
) -> Union[TFBaseModelOutput, Tuple[tf.Tensor]]:
|
| 502 |
+
all_hidden_states = () if output_hidden_states else None
|
| 503 |
+
all_attentions = () if output_attentions else None
|
| 504 |
+
|
| 505 |
+
for i, layer_module in enumerate(self.layers):
|
| 506 |
+
if output_hidden_states:
|
| 507 |
+
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 508 |
+
|
| 509 |
+
layer_outputs = layer_module(
|
| 510 |
+
hidden_states=hidden_states,
|
| 511 |
+
attention_mask=attention_mask,
|
| 512 |
+
causal_attention_mask=causal_attention_mask,
|
| 513 |
+
output_attentions=output_attentions,
|
| 514 |
+
training=training,
|
| 515 |
+
)
|
| 516 |
+
hidden_states = layer_outputs[0]
|
| 517 |
+
|
| 518 |
+
if output_attentions:
|
| 519 |
+
all_attentions = all_attentions + (layer_outputs[1],)
|
| 520 |
+
|
| 521 |
+
# Add last layer
|
| 522 |
+
if output_hidden_states:
|
| 523 |
+
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 524 |
+
|
| 525 |
+
if not return_dict:
|
| 526 |
+
return tuple(v for v in [hidden_states, all_hidden_states, all_attentions] if v is not None)
|
| 527 |
+
|
| 528 |
+
return TFBaseModelOutput(
|
| 529 |
+
last_hidden_state=hidden_states, hidden_states=all_hidden_states, attentions=all_attentions
|
| 530 |
+
)
|
| 531 |
+
|
| 532 |
+
def build(self, input_shape=None):
|
| 533 |
+
if self.built:
|
| 534 |
+
return
|
| 535 |
+
self.built = True
|
| 536 |
+
if getattr(self, "layers", None) is not None:
|
| 537 |
+
for layer in self.layers:
|
| 538 |
+
with tf.name_scope(layer.name):
|
| 539 |
+
layer.build(None)
|
| 540 |
+
|
| 541 |
+
|
| 542 |
+
class TFCLIPTextTransformer(keras.layers.Layer):
|
| 543 |
+
def __init__(self, config: CLIPTextConfig, **kwargs):
|
| 544 |
+
super().__init__(**kwargs)
|
| 545 |
+
|
| 546 |
+
self.embeddings = TFCLIPTextEmbeddings(config, name="embeddings")
|
| 547 |
+
self.encoder = TFCLIPEncoder(config, name="encoder")
|
| 548 |
+
self.final_layer_norm = keras.layers.LayerNormalization(epsilon=config.layer_norm_eps, name="final_layer_norm")
|
| 549 |
+
|
| 550 |
+
# For `pooled_output` computation
|
| 551 |
+
self.eos_token_id = config.eos_token_id
|
| 552 |
+
self.embed_dim = config.hidden_size
|
| 553 |
+
|
| 554 |
+
def call(
|
| 555 |
+
self,
|
| 556 |
+
input_ids: TFModelInputType,
|
| 557 |
+
attention_mask: tf.Tensor,
|
| 558 |
+
position_ids: tf.Tensor,
|
| 559 |
+
output_attentions: bool,
|
| 560 |
+
output_hidden_states: bool,
|
| 561 |
+
return_dict: bool,
|
| 562 |
+
training: bool = False,
|
| 563 |
+
) -> Union[TFBaseModelOutputWithPooling, Tuple[tf.Tensor]]:
|
| 564 |
+
input_shape = shape_list(input_ids)
|
| 565 |
+
|
| 566 |
+
embedding_output = self.embeddings(input_ids=input_ids, position_ids=position_ids)
|
| 567 |
+
|
| 568 |
+
batch_size, seq_length = input_shape
|
| 569 |
+
# CLIP's text model uses causal mask, prepare it here.
|
| 570 |
+
# https://github.com/openai/CLIP/blob/cfcffb90e69f37bf2ff1e988237a0fbe41f33c04/clip/model.py#L324
|
| 571 |
+
causal_attention_mask = self._build_causal_attention_mask(batch_size, seq_length, dtype=embedding_output.dtype)
|
| 572 |
+
|
| 573 |
+
# check attention mask and invert
|
| 574 |
+
# [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len]
|
| 575 |
+
attention_mask = _expand_mask(attention_mask)
|
| 576 |
+
|
| 577 |
+
encoder_outputs = self.encoder(
|
| 578 |
+
hidden_states=embedding_output,
|
| 579 |
+
attention_mask=attention_mask,
|
| 580 |
+
causal_attention_mask=causal_attention_mask,
|
| 581 |
+
output_attentions=output_attentions,
|
| 582 |
+
output_hidden_states=output_hidden_states,
|
| 583 |
+
return_dict=return_dict,
|
| 584 |
+
training=training,
|
| 585 |
+
)
|
| 586 |
+
|
| 587 |
+
sequence_output = encoder_outputs[0]
|
| 588 |
+
sequence_output = self.final_layer_norm(inputs=sequence_output)
|
| 589 |
+
|
| 590 |
+
if self.eos_token_id == 2:
|
| 591 |
+
# The `eos_token_id` was incorrect before PR #24773: Let's keep what have been done here.
|
| 592 |
+
# A CLIP model with such `eos_token_id` in the config can't work correctly with extra new tokens added
|
| 593 |
+
# ------------------------------------------------------------
|
| 594 |
+
# text_embeds.shape = [batch_size, n_ctx, transformer.width]
|
| 595 |
+
# take features from the eot embedding (eot_token is the highest number in each sequence)
|
| 596 |
+
pooled_output = tf.gather_nd(
|
| 597 |
+
params=sequence_output,
|
| 598 |
+
indices=tf.stack(
|
| 599 |
+
values=(tf.range(input_shape[0], dtype=tf.int64), tf.math.argmax(input_ids, axis=-1)), axis=1
|
| 600 |
+
),
|
| 601 |
+
)
|
| 602 |
+
else:
|
| 603 |
+
# The config gets updated `eos_token_id` from PR #24773 (so the use of exta new tokens is possible)
|
| 604 |
+
pooled_output = tf.gather_nd(
|
| 605 |
+
params=sequence_output,
|
| 606 |
+
indices=tf.stack(
|
| 607 |
+
values=(
|
| 608 |
+
tf.range(input_shape[0], dtype=tf.int64),
|
| 609 |
+
tf.math.argmax(tf.cast(input_ids == self.eos_token_id, dtype=tf.int8), axis=-1),
|
| 610 |
+
),
|
| 611 |
+
axis=1,
|
| 612 |
+
),
|
| 613 |
+
)
|
| 614 |
+
|
| 615 |
+
if not return_dict:
|
| 616 |
+
return (sequence_output, pooled_output) + encoder_outputs[1:]
|
| 617 |
+
|
| 618 |
+
return TFBaseModelOutputWithPooling(
|
| 619 |
+
last_hidden_state=sequence_output,
|
| 620 |
+
pooler_output=pooled_output,
|
| 621 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 622 |
+
attentions=encoder_outputs.attentions,
|
| 623 |
+
)
|
| 624 |
+
|
| 625 |
+
def _build_causal_attention_mask(self, batch_size, seq_length, dtype=tf.float32):
|
| 626 |
+
# It is possible with an unspecified sequence length for seq_length to be
|
| 627 |
+
# a runtime value, which is unsupported by tf.constant. Per the TensorFlow
|
| 628 |
+
# docs, tf.fill can handle runtime dynamic shapes:
|
| 629 |
+
# https://www.tensorflow.org/api_docs/python/tf/fill
|
| 630 |
+
diag = tf.cast(tf.fill((seq_length,), 0.0), dtype)
|
| 631 |
+
|
| 632 |
+
# set an additive 2D attention mask with all places being masked
|
| 633 |
+
to_mask = tf.cast(tf.fill((seq_length, seq_length), -10000.0), dtype)
|
| 634 |
+
|
| 635 |
+
# set diagonal & lower triangular parts to 0 (i.e. the places not to be masked)
|
| 636 |
+
# TIP: think the 2D matrix as the space of (query_seq, key_seq)
|
| 637 |
+
to_mask = tf.linalg.band_part(to_mask, 0, -1)
|
| 638 |
+
# to_mask = tf.linalg.band_part(to_mask, -1, 0)
|
| 639 |
+
to_mask = tf.linalg.set_diag(to_mask, diagonal=diag)
|
| 640 |
+
|
| 641 |
+
return tf.broadcast_to(input=to_mask, shape=(batch_size, 1, seq_length, seq_length))
|
| 642 |
+
|
| 643 |
+
def build(self, input_shape=None):
|
| 644 |
+
if self.built:
|
| 645 |
+
return
|
| 646 |
+
self.built = True
|
| 647 |
+
if getattr(self, "embeddings", None) is not None:
|
| 648 |
+
with tf.name_scope(self.embeddings.name):
|
| 649 |
+
self.embeddings.build(None)
|
| 650 |
+
if getattr(self, "encoder", None) is not None:
|
| 651 |
+
with tf.name_scope(self.encoder.name):
|
| 652 |
+
self.encoder.build(None)
|
| 653 |
+
if getattr(self, "final_layer_norm", None) is not None:
|
| 654 |
+
with tf.name_scope(self.final_layer_norm.name):
|
| 655 |
+
self.final_layer_norm.build([None, None, self.embed_dim])
|
| 656 |
+
|
| 657 |
+
|
| 658 |
+
@keras_serializable
|
| 659 |
+
class TFCLIPTextMainLayer(keras.layers.Layer):
|
| 660 |
+
config_class = CLIPTextConfig
|
| 661 |
+
|
| 662 |
+
def __init__(self, config: CLIPTextConfig, **kwargs):
|
| 663 |
+
super().__init__(**kwargs)
|
| 664 |
+
self.config = config
|
| 665 |
+
self.text_model = TFCLIPTextTransformer(config, name="text_model")
|
| 666 |
+
|
| 667 |
+
def get_input_embeddings(self) -> keras.layers.Layer:
|
| 668 |
+
return self.text_model.embeddings
|
| 669 |
+
|
| 670 |
+
def set_input_embeddings(self, value: tf.Variable):
|
| 671 |
+
self.text_model.embeddings.weight = value
|
| 672 |
+
self.text_model.embeddings.vocab_size = shape_list(value)[0]
|
| 673 |
+
|
| 674 |
+
@unpack_inputs
|
| 675 |
+
def call(
|
| 676 |
+
self,
|
| 677 |
+
input_ids: TFModelInputType | None = None,
|
| 678 |
+
attention_mask: np.ndarray | tf.Tensor | None = None,
|
| 679 |
+
position_ids: np.ndarray | tf.Tensor | None = None,
|
| 680 |
+
output_attentions: Optional[bool] = None,
|
| 681 |
+
output_hidden_states: Optional[bool] = None,
|
| 682 |
+
return_dict: Optional[bool] = None,
|
| 683 |
+
training: bool = False,
|
| 684 |
+
) -> Union[TFBaseModelOutputWithPooling, Tuple[tf.Tensor]]:
|
| 685 |
+
if input_ids is None:
|
| 686 |
+
raise ValueError("You have to specify input_ids")
|
| 687 |
+
|
| 688 |
+
input_shape = shape_list(input_ids)
|
| 689 |
+
|
| 690 |
+
if attention_mask is None:
|
| 691 |
+
attention_mask = tf.fill(dims=input_shape, value=1)
|
| 692 |
+
|
| 693 |
+
text_model_outputs = self.text_model(
|
| 694 |
+
input_ids=input_ids,
|
| 695 |
+
attention_mask=attention_mask,
|
| 696 |
+
position_ids=position_ids,
|
| 697 |
+
output_attentions=output_attentions,
|
| 698 |
+
output_hidden_states=output_hidden_states,
|
| 699 |
+
return_dict=return_dict,
|
| 700 |
+
training=training,
|
| 701 |
+
)
|
| 702 |
+
|
| 703 |
+
return text_model_outputs
|
| 704 |
+
|
| 705 |
+
def build(self, input_shape=None):
|
| 706 |
+
if self.built:
|
| 707 |
+
return
|
| 708 |
+
self.built = True
|
| 709 |
+
if getattr(self, "text_model", None) is not None:
|
| 710 |
+
with tf.name_scope(self.text_model.name):
|
| 711 |
+
self.text_model.build(None)
|
| 712 |
+
|
| 713 |
+
|
| 714 |
+
class TFCLIPVisionTransformer(keras.layers.Layer):
|
| 715 |
+
def __init__(self, config: CLIPVisionConfig, **kwargs):
|
| 716 |
+
super().__init__(**kwargs)
|
| 717 |
+
|
| 718 |
+
self.embeddings = TFCLIPVisionEmbeddings(config, name="embeddings")
|
| 719 |
+
self.pre_layernorm = keras.layers.LayerNormalization(epsilon=config.layer_norm_eps, name="pre_layrnorm")
|
| 720 |
+
self.encoder = TFCLIPEncoder(config, name="encoder")
|
| 721 |
+
self.post_layernorm = keras.layers.LayerNormalization(epsilon=config.layer_norm_eps, name="post_layernorm")
|
| 722 |
+
self.embed_dim = config.hidden_size
|
| 723 |
+
|
| 724 |
+
def call(
|
| 725 |
+
self,
|
| 726 |
+
pixel_values: TFModelInputType,
|
| 727 |
+
output_attentions: bool,
|
| 728 |
+
output_hidden_states: bool,
|
| 729 |
+
return_dict: bool,
|
| 730 |
+
training: bool = False,
|
| 731 |
+
) -> Union[TFBaseModelOutputWithPooling, Tuple[tf.Tensor]]:
|
| 732 |
+
embedding_output = self.embeddings(pixel_values=pixel_values)
|
| 733 |
+
embedding_output = self.pre_layernorm(inputs=embedding_output)
|
| 734 |
+
|
| 735 |
+
encoder_outputs = self.encoder(
|
| 736 |
+
hidden_states=embedding_output,
|
| 737 |
+
attention_mask=None,
|
| 738 |
+
causal_attention_mask=None,
|
| 739 |
+
output_attentions=output_attentions,
|
| 740 |
+
output_hidden_states=output_hidden_states,
|
| 741 |
+
return_dict=return_dict,
|
| 742 |
+
training=training,
|
| 743 |
+
)
|
| 744 |
+
|
| 745 |
+
sequence_output = encoder_outputs[0]
|
| 746 |
+
pooled_output = sequence_output[:, 0, :]
|
| 747 |
+
pooled_output = self.post_layernorm(inputs=pooled_output)
|
| 748 |
+
|
| 749 |
+
if not return_dict:
|
| 750 |
+
return (sequence_output, pooled_output) + encoder_outputs[1:]
|
| 751 |
+
|
| 752 |
+
return TFBaseModelOutputWithPooling(
|
| 753 |
+
last_hidden_state=sequence_output,
|
| 754 |
+
pooler_output=pooled_output,
|
| 755 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 756 |
+
attentions=encoder_outputs.attentions,
|
| 757 |
+
)
|
| 758 |
+
|
| 759 |
+
def build(self, input_shape=None):
|
| 760 |
+
if self.built:
|
| 761 |
+
return
|
| 762 |
+
self.built = True
|
| 763 |
+
if getattr(self, "embeddings", None) is not None:
|
| 764 |
+
with tf.name_scope(self.embeddings.name):
|
| 765 |
+
self.embeddings.build(None)
|
| 766 |
+
if getattr(self, "pre_layernorm", None) is not None:
|
| 767 |
+
with tf.name_scope(self.pre_layernorm.name):
|
| 768 |
+
self.pre_layernorm.build([None, None, self.embed_dim])
|
| 769 |
+
if getattr(self, "encoder", None) is not None:
|
| 770 |
+
with tf.name_scope(self.encoder.name):
|
| 771 |
+
self.encoder.build(None)
|
| 772 |
+
if getattr(self, "post_layernorm", None) is not None:
|
| 773 |
+
with tf.name_scope(self.post_layernorm.name):
|
| 774 |
+
self.post_layernorm.build([None, self.embed_dim])
|
| 775 |
+
|
| 776 |
+
|
| 777 |
+
@keras_serializable
|
| 778 |
+
class TFCLIPVisionMainLayer(keras.layers.Layer):
|
| 779 |
+
config_class = CLIPVisionConfig
|
| 780 |
+
|
| 781 |
+
def __init__(self, config: CLIPVisionConfig, **kwargs):
|
| 782 |
+
super().__init__(**kwargs)
|
| 783 |
+
self.config = config
|
| 784 |
+
self.vision_model = TFCLIPVisionTransformer(config, name="vision_model")
|
| 785 |
+
|
| 786 |
+
def get_input_embeddings(self) -> keras.layers.Layer:
|
| 787 |
+
return self.vision_model.embeddings
|
| 788 |
+
|
| 789 |
+
@unpack_inputs
|
| 790 |
+
def call(
|
| 791 |
+
self,
|
| 792 |
+
pixel_values: TFModelInputType | None = None,
|
| 793 |
+
output_attentions: Optional[bool] = None,
|
| 794 |
+
output_hidden_states: Optional[bool] = None,
|
| 795 |
+
return_dict: Optional[bool] = None,
|
| 796 |
+
training: bool = False,
|
| 797 |
+
) -> Union[TFBaseModelOutputWithPooling, Tuple[tf.Tensor]]:
|
| 798 |
+
if pixel_values is None:
|
| 799 |
+
raise ValueError("You have to specify pixel_values")
|
| 800 |
+
|
| 801 |
+
vision_model_outputs = self.vision_model(
|
| 802 |
+
pixel_values=pixel_values,
|
| 803 |
+
output_attentions=output_attentions,
|
| 804 |
+
output_hidden_states=output_hidden_states,
|
| 805 |
+
return_dict=return_dict,
|
| 806 |
+
training=training,
|
| 807 |
+
)
|
| 808 |
+
|
| 809 |
+
return vision_model_outputs
|
| 810 |
+
|
| 811 |
+
def build(self, input_shape=None):
|
| 812 |
+
if self.built:
|
| 813 |
+
return
|
| 814 |
+
self.built = True
|
| 815 |
+
if getattr(self, "vision_model", None) is not None:
|
| 816 |
+
with tf.name_scope(self.vision_model.name):
|
| 817 |
+
self.vision_model.build(None)
|
| 818 |
+
|
| 819 |
+
|
| 820 |
+
@keras_serializable
|
| 821 |
+
class TFCLIPMainLayer(keras.layers.Layer):
|
| 822 |
+
config_class = CLIPConfig
|
| 823 |
+
|
| 824 |
+
def __init__(self, config: CLIPConfig, **kwargs):
|
| 825 |
+
super().__init__(**kwargs)
|
| 826 |
+
|
| 827 |
+
if not isinstance(config.text_config, CLIPTextConfig):
|
| 828 |
+
raise TypeError(
|
| 829 |
+
"config.text_config is expected to be of type CLIPTextConfig but is of type"
|
| 830 |
+
f" {type(config.text_config)}."
|
| 831 |
+
)
|
| 832 |
+
|
| 833 |
+
if not isinstance(config.vision_config, CLIPVisionConfig):
|
| 834 |
+
raise TypeError(
|
| 835 |
+
"config.vision_config is expected to be of type CLIPVisionConfig but is of type"
|
| 836 |
+
f" {type(config.vision_config)}."
|
| 837 |
+
)
|
| 838 |
+
|
| 839 |
+
self.config = config
|
| 840 |
+
|
| 841 |
+
text_config = config.text_config
|
| 842 |
+
vision_config = config.vision_config
|
| 843 |
+
|
| 844 |
+
self.projection_dim = config.projection_dim
|
| 845 |
+
|
| 846 |
+
self.text_model = TFCLIPTextTransformer(text_config, name="text_model")
|
| 847 |
+
self.vision_model = TFCLIPVisionTransformer(vision_config, name="vision_model")
|
| 848 |
+
|
| 849 |
+
self.visual_projection = keras.layers.Dense(
|
| 850 |
+
units=self.projection_dim,
|
| 851 |
+
kernel_initializer=get_initializer(vision_config.hidden_size**-0.5 * self.config.initializer_factor),
|
| 852 |
+
use_bias=False,
|
| 853 |
+
name="visual_projection",
|
| 854 |
+
)
|
| 855 |
+
|
| 856 |
+
self.text_projection = keras.layers.Dense(
|
| 857 |
+
units=self.projection_dim,
|
| 858 |
+
kernel_initializer=get_initializer(text_config.hidden_size**-0.5 * self.config.initializer_factor),
|
| 859 |
+
use_bias=False,
|
| 860 |
+
name="text_projection",
|
| 861 |
+
)
|
| 862 |
+
self.text_embed_dim = text_config.hidden_size
|
| 863 |
+
self.vision_embed_dim = vision_config.hidden_size
|
| 864 |
+
|
| 865 |
+
def build(self, input_shape: tf.TensorShape = None):
|
| 866 |
+
self.logit_scale = self.add_weight(
|
| 867 |
+
shape=(1,),
|
| 868 |
+
initializer=keras.initializers.Constant(self.config.logit_scale_init_value),
|
| 869 |
+
trainable=True,
|
| 870 |
+
name="logit_scale",
|
| 871 |
+
)
|
| 872 |
+
|
| 873 |
+
if self.built:
|
| 874 |
+
return
|
| 875 |
+
self.built = True
|
| 876 |
+
if getattr(self, "text_model", None) is not None:
|
| 877 |
+
with tf.name_scope(self.text_model.name):
|
| 878 |
+
self.text_model.build(None)
|
| 879 |
+
if getattr(self, "vision_model", None) is not None:
|
| 880 |
+
with tf.name_scope(self.vision_model.name):
|
| 881 |
+
self.vision_model.build(None)
|
| 882 |
+
if getattr(self, "visual_projection", None) is not None:
|
| 883 |
+
with tf.name_scope(self.visual_projection.name):
|
| 884 |
+
self.visual_projection.build([None, None, self.vision_embed_dim])
|
| 885 |
+
if getattr(self, "text_projection", None) is not None:
|
| 886 |
+
with tf.name_scope(self.text_projection.name):
|
| 887 |
+
self.text_projection.build([None, None, self.text_embed_dim])
|
| 888 |
+
|
| 889 |
+
@unpack_inputs
|
| 890 |
+
def get_text_features(
|
| 891 |
+
self,
|
| 892 |
+
input_ids: TFModelInputType | None = None,
|
| 893 |
+
attention_mask: np.ndarray | tf.Tensor | None = None,
|
| 894 |
+
position_ids: np.ndarray | tf.Tensor | None = None,
|
| 895 |
+
output_attentions: Optional[bool] = None,
|
| 896 |
+
output_hidden_states: Optional[bool] = None,
|
| 897 |
+
return_dict: Optional[bool] = None,
|
| 898 |
+
training: bool = False,
|
| 899 |
+
) -> tf.Tensor:
|
| 900 |
+
if input_ids is None:
|
| 901 |
+
raise ValueError("You have to specify either input_ids")
|
| 902 |
+
|
| 903 |
+
input_shape = shape_list(input_ids)
|
| 904 |
+
|
| 905 |
+
if attention_mask is None:
|
| 906 |
+
attention_mask = tf.fill(dims=input_shape, value=1)
|
| 907 |
+
|
| 908 |
+
text_outputs = self.text_model(
|
| 909 |
+
input_ids=input_ids,
|
| 910 |
+
attention_mask=attention_mask,
|
| 911 |
+
position_ids=position_ids,
|
| 912 |
+
output_attentions=output_attentions,
|
| 913 |
+
output_hidden_states=output_hidden_states,
|
| 914 |
+
return_dict=return_dict,
|
| 915 |
+
training=training,
|
| 916 |
+
)
|
| 917 |
+
|
| 918 |
+
pooled_output = text_outputs[1]
|
| 919 |
+
text_features = self.text_projection(inputs=pooled_output)
|
| 920 |
+
|
| 921 |
+
return text_features
|
| 922 |
+
|
| 923 |
+
@unpack_inputs
|
| 924 |
+
def get_image_features(
|
| 925 |
+
self,
|
| 926 |
+
pixel_values: TFModelInputType | None = None,
|
| 927 |
+
output_attentions: Optional[bool] = None,
|
| 928 |
+
output_hidden_states: Optional[bool] = None,
|
| 929 |
+
return_dict: Optional[bool] = None,
|
| 930 |
+
training: bool = False,
|
| 931 |
+
) -> tf.Tensor:
|
| 932 |
+
if pixel_values is None:
|
| 933 |
+
raise ValueError("You have to specify pixel_values")
|
| 934 |
+
|
| 935 |
+
vision_outputs = self.vision_model(
|
| 936 |
+
pixel_values=pixel_values,
|
| 937 |
+
output_attentions=output_attentions,
|
| 938 |
+
output_hidden_states=output_hidden_states,
|
| 939 |
+
return_dict=return_dict,
|
| 940 |
+
training=training,
|
| 941 |
+
)
|
| 942 |
+
|
| 943 |
+
pooled_output = vision_outputs[1] # pooled_output
|
| 944 |
+
image_features = self.visual_projection(inputs=pooled_output)
|
| 945 |
+
|
| 946 |
+
return image_features
|
| 947 |
+
|
| 948 |
+
@unpack_inputs
|
| 949 |
+
def call(
|
| 950 |
+
self,
|
| 951 |
+
input_ids: TFModelInputType | None = None,
|
| 952 |
+
pixel_values: TFModelInputType | None = None,
|
| 953 |
+
attention_mask: np.ndarray | tf.Tensor | None = None,
|
| 954 |
+
position_ids: np.ndarray | tf.Tensor | None = None,
|
| 955 |
+
return_loss: Optional[bool] = None,
|
| 956 |
+
output_attentions: Optional[bool] = None,
|
| 957 |
+
output_hidden_states: Optional[bool] = None,
|
| 958 |
+
return_dict: Optional[bool] = None,
|
| 959 |
+
training: bool = False,
|
| 960 |
+
) -> Union[TFCLIPOutput, Tuple[tf.Tensor]]:
|
| 961 |
+
if input_ids is None:
|
| 962 |
+
raise ValueError("You have to specify either input_ids")
|
| 963 |
+
if pixel_values is None:
|
| 964 |
+
raise ValueError("You have to specify pixel_values")
|
| 965 |
+
|
| 966 |
+
input_shape = shape_list(input_ids)
|
| 967 |
+
|
| 968 |
+
if attention_mask is None:
|
| 969 |
+
attention_mask = tf.fill(dims=input_shape, value=1)
|
| 970 |
+
|
| 971 |
+
vision_outputs = self.vision_model(
|
| 972 |
+
pixel_values=pixel_values,
|
| 973 |
+
output_attentions=output_attentions,
|
| 974 |
+
output_hidden_states=output_hidden_states,
|
| 975 |
+
return_dict=return_dict,
|
| 976 |
+
training=training,
|
| 977 |
+
)
|
| 978 |
+
|
| 979 |
+
text_outputs = self.text_model(
|
| 980 |
+
input_ids=input_ids,
|
| 981 |
+
attention_mask=attention_mask,
|
| 982 |
+
position_ids=position_ids,
|
| 983 |
+
output_attentions=output_attentions,
|
| 984 |
+
output_hidden_states=output_hidden_states,
|
| 985 |
+
return_dict=return_dict,
|
| 986 |
+
training=training,
|
| 987 |
+
)
|
| 988 |
+
|
| 989 |
+
image_embeds = vision_outputs[1]
|
| 990 |
+
image_embeds = self.visual_projection(inputs=image_embeds)
|
| 991 |
+
|
| 992 |
+
text_embeds = text_outputs[1]
|
| 993 |
+
text_embeds = self.text_projection(inputs=text_embeds)
|
| 994 |
+
|
| 995 |
+
# normalized features
|
| 996 |
+
image_embeds = image_embeds / tf.norm(tensor=image_embeds, ord="euclidean", axis=-1, keepdims=True)
|
| 997 |
+
text_embeds = text_embeds / tf.norm(tensor=text_embeds, ord="euclidean", axis=-1, keepdims=True)
|
| 998 |
+
|
| 999 |
+
# cosine similarity as logits
|
| 1000 |
+
logit_scale = tf.math.exp(self.logit_scale)
|
| 1001 |
+
logits_per_text = tf.matmul(text_embeds, image_embeds, transpose_b=True) * logit_scale
|
| 1002 |
+
logits_per_image = tf.transpose(logits_per_text)
|
| 1003 |
+
|
| 1004 |
+
loss = None
|
| 1005 |
+
if return_loss:
|
| 1006 |
+
loss = clip_loss(logits_per_text)
|
| 1007 |
+
loss = tf.reshape(loss, (1,))
|
| 1008 |
+
|
| 1009 |
+
if not return_dict:
|
| 1010 |
+
output = (logits_per_image, logits_per_text, text_embeds, image_embeds, text_outputs, vision_outputs)
|
| 1011 |
+
return (loss,) + output if loss is not None else output
|
| 1012 |
+
|
| 1013 |
+
return TFCLIPOutput(
|
| 1014 |
+
loss=loss,
|
| 1015 |
+
logits_per_image=logits_per_image,
|
| 1016 |
+
logits_per_text=logits_per_text,
|
| 1017 |
+
text_embeds=text_embeds,
|
| 1018 |
+
image_embeds=image_embeds,
|
| 1019 |
+
text_model_output=text_outputs,
|
| 1020 |
+
vision_model_output=vision_outputs,
|
| 1021 |
+
)
|
| 1022 |
+
|
| 1023 |
+
|
| 1024 |
+
class TFCLIPPreTrainedModel(TFPreTrainedModel):
|
| 1025 |
+
"""
|
| 1026 |
+
An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained
|
| 1027 |
+
models.
|
| 1028 |
+
"""
|
| 1029 |
+
|
| 1030 |
+
config_class = CLIPConfig
|
| 1031 |
+
base_model_prefix = "clip"
|
| 1032 |
+
_keys_to_ignore_on_load_missing = [r"position_ids"]
|
| 1033 |
+
_keys_to_ignore_on_load_unexpected = [r"position_ids"]
|
| 1034 |
+
|
| 1035 |
+
|
| 1036 |
+
CLIP_START_DOCSTRING = r"""
|
| 1037 |
+
|
| 1038 |
+
This model inherits from [`TFPreTrainedModel`]. Check the superclass documentation for the generic methods the
|
| 1039 |
+
library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads
|
| 1040 |
+
etc.)
|
| 1041 |
+
|
| 1042 |
+
This model is also a [keras.Model](https://www.tensorflow.org/api_docs/python/tf/keras/Model) subclass. Use it
|
| 1043 |
+
as a regular TF 2.0 Keras Model and refer to the TF 2.0 documentation for all matter related to general usage and
|
| 1044 |
+
behavior.
|
| 1045 |
+
|
| 1046 |
+
<Tip>
|
| 1047 |
+
|
| 1048 |
+
TensorFlow models and layers in `transformers` accept two formats as input:
|
| 1049 |
+
|
| 1050 |
+
- having all inputs as keyword arguments (like PyTorch models), or
|
| 1051 |
+
- having all inputs as a list, tuple or dict in the first positional argument.
|
| 1052 |
+
|
| 1053 |
+
The reason the second format is supported is that Keras methods prefer this format when passing inputs to models
|
| 1054 |
+
and layers. Because of this support, when using methods like `model.fit()` things should "just work" for you - just
|
| 1055 |
+
pass your inputs and labels in any format that `model.fit()` supports! If, however, you want to use the second
|
| 1056 |
+
format outside of Keras methods like `fit()` and `predict()`, such as when creating your own layers or models with
|
| 1057 |
+
the Keras `Functional` API, there are three possibilities you can use to gather all the input Tensors in the first
|
| 1058 |
+
positional argument:
|
| 1059 |
+
|
| 1060 |
+
- a single Tensor with `input_ids` only and nothing else: `model(input_ids)`
|
| 1061 |
+
- a list of varying length with one or several input Tensors IN THE ORDER given in the docstring:
|
| 1062 |
+
`model([input_ids, attention_mask])` or `model([input_ids, attention_mask, token_type_ids])`
|
| 1063 |
+
- a dictionary with one or several input Tensors associated to the input names given in the docstring:
|
| 1064 |
+
`model({"input_ids": input_ids, "token_type_ids": token_type_ids})`
|
| 1065 |
+
|
| 1066 |
+
Note that when creating models and layers with
|
| 1067 |
+
[subclassing](https://keras.io/guides/making_new_layers_and_models_via_subclassing/) then you don't need to worry
|
| 1068 |
+
about any of this, as you can just pass inputs like you would to any other Python function!
|
| 1069 |
+
|
| 1070 |
+
</Tip>
|
| 1071 |
+
|
| 1072 |
+
Args:
|
| 1073 |
+
config ([`CLIPConfig`]): Model configuration class with all the parameters of the model.
|
| 1074 |
+
Initializing with a config file does not load the weights associated with the model, only the
|
| 1075 |
+
configuration. Check out the [`~TFPreTrainedModel.from_pretrained`] method to load the model weights.
|
| 1076 |
+
"""
|
| 1077 |
+
|
| 1078 |
+
CLIP_TEXT_INPUTS_DOCSTRING = r"""
|
| 1079 |
+
Args:
|
| 1080 |
+
input_ids (`np.ndarray`, `tf.Tensor`, `List[tf.Tensor]` ``Dict[str, tf.Tensor]` or `Dict[str, np.ndarray]` and each example must have the shape `({0})`):
|
| 1081 |
+
Indices of input sequence tokens in the vocabulary.
|
| 1082 |
+
|
| 1083 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.__call__`] and
|
| 1084 |
+
[`PreTrainedTokenizer.encode`] for details.
|
| 1085 |
+
|
| 1086 |
+
[What are input IDs?](../glossary#input-ids)
|
| 1087 |
+
attention_mask (`np.ndarray` or `tf.Tensor` of shape `({0})`, *optional*):
|
| 1088 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 1089 |
+
|
| 1090 |
+
- 1 for tokens that are **not masked**,
|
| 1091 |
+
- 0 for tokens that are **masked**.
|
| 1092 |
+
|
| 1093 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 1094 |
+
position_ids (`np.ndarray` or `tf.Tensor` of shape `({0})`, *optional*):
|
| 1095 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 1096 |
+
config.max_position_embeddings - 1]`.
|
| 1097 |
+
|
| 1098 |
+
[What are position IDs?](../glossary#position-ids)
|
| 1099 |
+
output_attentions (`bool`, *optional*):
|
| 1100 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 1101 |
+
tensors for more detail. This argument can be used only in eager mode, in graph mode the value in the
|
| 1102 |
+
config will be used instead.
|
| 1103 |
+
output_hidden_states (`bool`, *optional*):
|
| 1104 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 1105 |
+
more detail. This argument can be used only in eager mode, in graph mode the value in the config will be
|
| 1106 |
+
used instead.
|
| 1107 |
+
return_dict (`bool`, *optional*):
|
| 1108 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple. This argument can be used in
|
| 1109 |
+
eager mode, in graph mode the value will always be set to True.
|
| 1110 |
+
training (`bool`, *optional*, defaults to `False``):
|
| 1111 |
+
Whether or not to use the model in training mode (some modules like dropout modules have different
|
| 1112 |
+
behaviors between training and evaluation).
|
| 1113 |
+
"""
|
| 1114 |
+
|
| 1115 |
+
CLIP_VISION_INPUTS_DOCSTRING = r"""
|
| 1116 |
+
Args:
|
| 1117 |
+
pixel_values (`np.ndarray`, `tf.Tensor`, `List[tf.Tensor]` ``Dict[str, tf.Tensor]` or `Dict[str, np.ndarray]` and each example must have the shape `(batch_size, num_channels, height, width)`):
|
| 1118 |
+
Pixel values. Pixel values can be obtained using [`AutoImageProcessor`]. See
|
| 1119 |
+
[`CLIPImageProcessor.__call__`] for details. output_attentions (`bool`, *optional*): Whether or not to
|
| 1120 |
+
return the attentions tensors of all attention layers. See `attentions` under returned tensors for more
|
| 1121 |
+
detail. This argument can be used only in eager mode, in graph mode the value in the config will be used
|
| 1122 |
+
instead.
|
| 1123 |
+
output_hidden_states (`bool`, *optional*):
|
| 1124 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 1125 |
+
more detail. This argument can be used only in eager mode, in graph mode the value in the config will be
|
| 1126 |
+
used instead.
|
| 1127 |
+
return_dict (`bool`, *optional*):
|
| 1128 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple. This argument can be used in
|
| 1129 |
+
eager mode, in graph mode the value will always be set to True.
|
| 1130 |
+
training (`bool`, *optional*, defaults to `False``):
|
| 1131 |
+
Whether or not to use the model in training mode (some modules like dropout modules have different
|
| 1132 |
+
behaviors between training and evaluation).
|
| 1133 |
+
"""
|
| 1134 |
+
|
| 1135 |
+
CLIP_INPUTS_DOCSTRING = r"""
|
| 1136 |
+
Args:
|
| 1137 |
+
input_ids (`np.ndarray`, `tf.Tensor`, `List[tf.Tensor]` ``Dict[str, tf.Tensor]` or `Dict[str, np.ndarray]` and each example must have the shape `({0})`):
|
| 1138 |
+
Indices of input sequence tokens in the vocabulary.
|
| 1139 |
+
|
| 1140 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.__call__`] and
|
| 1141 |
+
[`PreTrainedTokenizer.encode`] for details.
|
| 1142 |
+
|
| 1143 |
+
[What are input IDs?](../glossary#input-ids)
|
| 1144 |
+
pixel_values (`np.ndarray`, `tf.Tensor`, `List[tf.Tensor]` `Dict[str, tf.Tensor]` or `Dict[str, np.ndarray]` and each example must have the shape `(batch_size, num_channels, height, width)`):
|
| 1145 |
+
Pixel values. Pixel values can be obtained using [`AutoImageProcessor`]. See
|
| 1146 |
+
[`CLIPImageProcessor.__call__`] for details.
|
| 1147 |
+
attention_mask (`np.ndarray` or `tf.Tensor` of shape `({0})`, *optional*):
|
| 1148 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 1149 |
+
|
| 1150 |
+
- 1 for tokens that are **not masked**,
|
| 1151 |
+
- 0 for tokens that are **masked**.
|
| 1152 |
+
|
| 1153 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 1154 |
+
position_ids (`np.ndarray` or `tf.Tensor` of shape `({0})`, *optional*):
|
| 1155 |
+
Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
|
| 1156 |
+
config.max_position_embeddings - 1]`.
|
| 1157 |
+
|
| 1158 |
+
[What are position IDs?](../glossary#position-ids)
|
| 1159 |
+
return_loss (`bool`, *optional*):
|
| 1160 |
+
Whether or not to return the contrastive loss.
|
| 1161 |
+
output_attentions (`bool`, *optional*):
|
| 1162 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
|
| 1163 |
+
tensors for more detail. This argument can be used only in eager mode, in graph mode the value in the
|
| 1164 |
+
config will be used instead.
|
| 1165 |
+
output_hidden_states (`bool`, *optional*):
|
| 1166 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
|
| 1167 |
+
more detail. This argument can be used only in eager mode, in graph mode the value in the config will be
|
| 1168 |
+
used instead.
|
| 1169 |
+
return_dict (`bool`, *optional*):
|
| 1170 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple. This argument can be used in
|
| 1171 |
+
eager mode, in graph mode the value will always be set to True.
|
| 1172 |
+
training (`bool`, *optional*, defaults to `False``):
|
| 1173 |
+
Whether or not to use the model in training mode (some modules like dropout modules have different
|
| 1174 |
+
behaviors between training and evaluation).
|
| 1175 |
+
"""
|
| 1176 |
+
|
| 1177 |
+
|
| 1178 |
+
class TFCLIPTextModel(TFCLIPPreTrainedModel):
|
| 1179 |
+
config_class = CLIPTextConfig
|
| 1180 |
+
|
| 1181 |
+
def __init__(self, config: CLIPTextConfig, *inputs, **kwargs):
|
| 1182 |
+
super().__init__(config, *inputs, **kwargs)
|
| 1183 |
+
|
| 1184 |
+
self.clip = TFCLIPTextMainLayer(config, name="clip")
|
| 1185 |
+
|
| 1186 |
+
@unpack_inputs
|
| 1187 |
+
@add_start_docstrings_to_model_forward(CLIP_TEXT_INPUTS_DOCSTRING.format("batch_size, sequence_length"))
|
| 1188 |
+
@replace_return_docstrings(output_type=TFBaseModelOutputWithPooling, config_class=CLIPTextConfig)
|
| 1189 |
+
def call(
|
| 1190 |
+
self,
|
| 1191 |
+
input_ids: TFModelInputType | None = None,
|
| 1192 |
+
attention_mask: np.ndarray | tf.Tensor | None = None,
|
| 1193 |
+
position_ids: np.ndarray | tf.Tensor | None = None,
|
| 1194 |
+
output_attentions: Optional[bool] = None,
|
| 1195 |
+
output_hidden_states: Optional[bool] = None,
|
| 1196 |
+
return_dict: Optional[bool] = None,
|
| 1197 |
+
training: Optional[bool] = False,
|
| 1198 |
+
) -> Union[TFBaseModelOutputWithPooling, Tuple[tf.Tensor]]:
|
| 1199 |
+
r"""
|
| 1200 |
+
Returns:
|
| 1201 |
+
|
| 1202 |
+
Examples:
|
| 1203 |
+
|
| 1204 |
+
```python
|
| 1205 |
+
>>> from transformers import AutoTokenizer, TFCLIPTextModel
|
| 1206 |
+
|
| 1207 |
+
>>> model = TFCLIPTextModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1208 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 1209 |
+
|
| 1210 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="tf")
|
| 1211 |
+
|
| 1212 |
+
>>> outputs = model(**inputs)
|
| 1213 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 1214 |
+
>>> pooled_output = outputs.pooler_output # pooled (EOS token) states
|
| 1215 |
+
```"""
|
| 1216 |
+
|
| 1217 |
+
outputs = self.clip(
|
| 1218 |
+
input_ids=input_ids,
|
| 1219 |
+
attention_mask=attention_mask,
|
| 1220 |
+
position_ids=position_ids,
|
| 1221 |
+
output_attentions=output_attentions,
|
| 1222 |
+
output_hidden_states=output_hidden_states,
|
| 1223 |
+
return_dict=return_dict,
|
| 1224 |
+
training=training,
|
| 1225 |
+
)
|
| 1226 |
+
|
| 1227 |
+
return outputs
|
| 1228 |
+
|
| 1229 |
+
def build(self, input_shape=None):
|
| 1230 |
+
if self.built:
|
| 1231 |
+
return
|
| 1232 |
+
self.built = True
|
| 1233 |
+
if getattr(self, "clip", None) is not None:
|
| 1234 |
+
with tf.name_scope(self.clip.name):
|
| 1235 |
+
self.clip.build(None)
|
| 1236 |
+
|
| 1237 |
+
|
| 1238 |
+
class TFCLIPVisionModel(TFCLIPPreTrainedModel):
|
| 1239 |
+
config_class = CLIPVisionConfig
|
| 1240 |
+
main_input_name = "pixel_values"
|
| 1241 |
+
|
| 1242 |
+
def __init__(self, config: CLIPVisionConfig, *inputs, **kwargs):
|
| 1243 |
+
super().__init__(config, *inputs, **kwargs)
|
| 1244 |
+
|
| 1245 |
+
self.clip = TFCLIPVisionMainLayer(config, name="clip")
|
| 1246 |
+
|
| 1247 |
+
@unpack_inputs
|
| 1248 |
+
@add_start_docstrings_to_model_forward(CLIP_VISION_INPUTS_DOCSTRING)
|
| 1249 |
+
@replace_return_docstrings(output_type=TFBaseModelOutputWithPooling, config_class=CLIPVisionConfig)
|
| 1250 |
+
def call(
|
| 1251 |
+
self,
|
| 1252 |
+
pixel_values: TFModelInputType | None = None,
|
| 1253 |
+
output_attentions: Optional[bool] = None,
|
| 1254 |
+
output_hidden_states: Optional[bool] = None,
|
| 1255 |
+
return_dict: Optional[bool] = None,
|
| 1256 |
+
training: Optional[bool] = False,
|
| 1257 |
+
) -> Union[TFBaseModelOutputWithPooling, Tuple[tf.Tensor]]:
|
| 1258 |
+
r"""
|
| 1259 |
+
Returns:
|
| 1260 |
+
|
| 1261 |
+
Examples:
|
| 1262 |
+
|
| 1263 |
+
```python
|
| 1264 |
+
>>> from PIL import Image
|
| 1265 |
+
>>> import requests
|
| 1266 |
+
>>> from transformers import AutoProcessor, TFCLIPVisionModel
|
| 1267 |
+
|
| 1268 |
+
>>> model = TFCLIPVisionModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1269 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1270 |
+
|
| 1271 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1272 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1273 |
+
|
| 1274 |
+
>>> inputs = processor(images=image, return_tensors="tf")
|
| 1275 |
+
|
| 1276 |
+
>>> outputs = model(**inputs)
|
| 1277 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 1278 |
+
>>> pooled_output = outputs.pooler_output # pooled CLS states
|
| 1279 |
+
```"""
|
| 1280 |
+
|
| 1281 |
+
outputs = self.clip(
|
| 1282 |
+
pixel_values=pixel_values,
|
| 1283 |
+
output_attentions=output_attentions,
|
| 1284 |
+
output_hidden_states=output_hidden_states,
|
| 1285 |
+
return_dict=return_dict,
|
| 1286 |
+
training=training,
|
| 1287 |
+
)
|
| 1288 |
+
|
| 1289 |
+
return outputs
|
| 1290 |
+
|
| 1291 |
+
def build(self, input_shape=None):
|
| 1292 |
+
if self.built:
|
| 1293 |
+
return
|
| 1294 |
+
self.built = True
|
| 1295 |
+
if getattr(self, "clip", None) is not None:
|
| 1296 |
+
with tf.name_scope(self.clip.name):
|
| 1297 |
+
self.clip.build(None)
|
| 1298 |
+
|
| 1299 |
+
|
| 1300 |
+
@add_start_docstrings(CLIP_START_DOCSTRING)
|
| 1301 |
+
class TFCLIPModel(TFCLIPPreTrainedModel):
|
| 1302 |
+
config_class = CLIPConfig
|
| 1303 |
+
|
| 1304 |
+
def __init__(self, config: CLIPConfig, *inputs, **kwargs):
|
| 1305 |
+
super().__init__(config, *inputs, **kwargs)
|
| 1306 |
+
|
| 1307 |
+
self.clip = TFCLIPMainLayer(config, name="clip")
|
| 1308 |
+
|
| 1309 |
+
@unpack_inputs
|
| 1310 |
+
@add_start_docstrings_to_model_forward(CLIP_TEXT_INPUTS_DOCSTRING.format("batch_size, sequence_length"))
|
| 1311 |
+
def get_text_features(
|
| 1312 |
+
self,
|
| 1313 |
+
input_ids: TFModelInputType | None = None,
|
| 1314 |
+
attention_mask: np.ndarray | tf.Tensor | None = None,
|
| 1315 |
+
position_ids: np.ndarray | tf.Tensor | None = None,
|
| 1316 |
+
output_attentions: Optional[bool] = None,
|
| 1317 |
+
output_hidden_states: Optional[bool] = None,
|
| 1318 |
+
return_dict: Optional[bool] = None,
|
| 1319 |
+
training: bool = False,
|
| 1320 |
+
) -> tf.Tensor:
|
| 1321 |
+
r"""
|
| 1322 |
+
Returns:
|
| 1323 |
+
text_features (`tf.Tensor` of shape `(batch_size, output_dim`): The text embeddings obtained by applying
|
| 1324 |
+
the projection layer to the pooled output of [`TFCLIPTextModel`].
|
| 1325 |
+
|
| 1326 |
+
Examples:
|
| 1327 |
+
|
| 1328 |
+
```python
|
| 1329 |
+
>>> from transformers import AutoTokenizer, TFCLIPModel
|
| 1330 |
+
|
| 1331 |
+
>>> model = TFCLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1332 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 1333 |
+
|
| 1334 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="tf")
|
| 1335 |
+
>>> text_features = model.get_text_features(**inputs)
|
| 1336 |
+
```"""
|
| 1337 |
+
|
| 1338 |
+
text_features = self.clip.get_text_features(
|
| 1339 |
+
input_ids=input_ids,
|
| 1340 |
+
attention_mask=attention_mask,
|
| 1341 |
+
position_ids=position_ids,
|
| 1342 |
+
output_attentions=output_attentions,
|
| 1343 |
+
output_hidden_states=output_hidden_states,
|
| 1344 |
+
return_dict=return_dict,
|
| 1345 |
+
)
|
| 1346 |
+
|
| 1347 |
+
return text_features
|
| 1348 |
+
|
| 1349 |
+
@unpack_inputs
|
| 1350 |
+
@add_start_docstrings_to_model_forward(CLIP_VISION_INPUTS_DOCSTRING)
|
| 1351 |
+
def get_image_features(
|
| 1352 |
+
self,
|
| 1353 |
+
pixel_values: TFModelInputType | None = None,
|
| 1354 |
+
output_attentions: Optional[bool] = None,
|
| 1355 |
+
output_hidden_states: Optional[bool] = None,
|
| 1356 |
+
return_dict: Optional[bool] = None,
|
| 1357 |
+
training: bool = False,
|
| 1358 |
+
) -> tf.Tensor:
|
| 1359 |
+
r"""
|
| 1360 |
+
Returns:
|
| 1361 |
+
image_features (`tf.Tensor` of shape `(batch_size, output_dim`): The image embeddings obtained by applying
|
| 1362 |
+
the projection layer to the pooled output of [`TFCLIPVisionModel`].
|
| 1363 |
+
|
| 1364 |
+
Examples:
|
| 1365 |
+
|
| 1366 |
+
```python
|
| 1367 |
+
>>> from PIL import Image
|
| 1368 |
+
>>> import requests
|
| 1369 |
+
>>> from transformers import AutoProcessor, TFCLIPModel
|
| 1370 |
+
|
| 1371 |
+
>>> model = TFCLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1372 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1373 |
+
|
| 1374 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1375 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1376 |
+
|
| 1377 |
+
>>> inputs = processor(images=image, return_tensors="tf")
|
| 1378 |
+
|
| 1379 |
+
>>> image_features = model.get_image_features(**inputs)
|
| 1380 |
+
```"""
|
| 1381 |
+
|
| 1382 |
+
image_features = self.clip.get_image_features(
|
| 1383 |
+
pixel_values=pixel_values,
|
| 1384 |
+
output_attentions=output_attentions,
|
| 1385 |
+
output_hidden_states=output_hidden_states,
|
| 1386 |
+
return_dict=return_dict,
|
| 1387 |
+
)
|
| 1388 |
+
|
| 1389 |
+
return image_features
|
| 1390 |
+
|
| 1391 |
+
@unpack_inputs
|
| 1392 |
+
@add_start_docstrings_to_model_forward(CLIP_INPUTS_DOCSTRING.format("batch_size, sequence_length"))
|
| 1393 |
+
@replace_return_docstrings(output_type=TFCLIPOutput, config_class=CLIPConfig)
|
| 1394 |
+
def call(
|
| 1395 |
+
self,
|
| 1396 |
+
input_ids: TFModelInputType | None = None,
|
| 1397 |
+
pixel_values: TFModelInputType | None = None,
|
| 1398 |
+
attention_mask: np.ndarray | tf.Tensor | None = None,
|
| 1399 |
+
position_ids: np.ndarray | tf.Tensor | None = None,
|
| 1400 |
+
return_loss: Optional[bool] = None,
|
| 1401 |
+
output_attentions: Optional[bool] = None,
|
| 1402 |
+
output_hidden_states: Optional[bool] = None,
|
| 1403 |
+
return_dict: Optional[bool] = None,
|
| 1404 |
+
training: bool = False,
|
| 1405 |
+
) -> Union[TFCLIPOutput, Tuple[tf.Tensor]]:
|
| 1406 |
+
r"""
|
| 1407 |
+
Returns:
|
| 1408 |
+
|
| 1409 |
+
Examples:
|
| 1410 |
+
|
| 1411 |
+
```python
|
| 1412 |
+
>>> import tensorflow as tf
|
| 1413 |
+
>>> from PIL import Image
|
| 1414 |
+
>>> import requests
|
| 1415 |
+
>>> from transformers import AutoProcessor, TFCLIPModel
|
| 1416 |
+
|
| 1417 |
+
>>> model = TFCLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 1418 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1419 |
+
|
| 1420 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1421 |
+
>>> image = Image.open(requests.get(url, stream=True).raw)
|
| 1422 |
+
|
| 1423 |
+
>>> inputs = processor(
|
| 1424 |
+
... text=["a photo of a cat", "a photo of a dog"], images=image, return_tensors="tf", padding=True
|
| 1425 |
+
... )
|
| 1426 |
+
|
| 1427 |
+
>>> outputs = model(**inputs)
|
| 1428 |
+
>>> logits_per_image = outputs.logits_per_image # this is the image-text similarity score
|
| 1429 |
+
>>> probs = tf.nn.softmax(logits_per_image, axis=1) # we can take the softmax to get the label probabilities
|
| 1430 |
+
```"""
|
| 1431 |
+
|
| 1432 |
+
outputs = self.clip(
|
| 1433 |
+
input_ids=input_ids,
|
| 1434 |
+
pixel_values=pixel_values,
|
| 1435 |
+
attention_mask=attention_mask,
|
| 1436 |
+
position_ids=position_ids,
|
| 1437 |
+
return_loss=return_loss,
|
| 1438 |
+
output_attentions=output_attentions,
|
| 1439 |
+
output_hidden_states=output_hidden_states,
|
| 1440 |
+
return_dict=return_dict,
|
| 1441 |
+
)
|
| 1442 |
+
|
| 1443 |
+
return outputs
|
| 1444 |
+
|
| 1445 |
+
def serving_output(self, output: TFCLIPOutput) -> TFCLIPOutput:
|
| 1446 |
+
# TODO: As is this currently fails with saved_model=True, because
|
| 1447 |
+
# TensorFlow cannot trace through nested dataclasses. Reference:
|
| 1448 |
+
# https://github.com/huggingface/transformers/pull/16886
|
| 1449 |
+
return output
|
| 1450 |
+
|
| 1451 |
+
def build(self, input_shape=None):
|
| 1452 |
+
if self.built:
|
| 1453 |
+
return
|
| 1454 |
+
self.built = True
|
| 1455 |
+
if getattr(self, "clip", None) is not None:
|
| 1456 |
+
with tf.name_scope(self.clip.name):
|
| 1457 |
+
self.clip.build(None)
|
| 1458 |
+
|
| 1459 |
+
|
| 1460 |
+
__all__ = ["TFCLIPModel", "TFCLIPPreTrainedModel", "TFCLIPTextModel", "TFCLIPVisionModel"]
|
lib/python3.12/site-packages/transformers/models/clip/processing_clip.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2021 The HuggingFace Inc. team.
|
| 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 |
+
"""
|
| 16 |
+
Image/Text processor class for CLIP
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import warnings
|
| 20 |
+
|
| 21 |
+
from ...processing_utils import ProcessorMixin
|
| 22 |
+
from ...tokenization_utils_base import BatchEncoding
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class CLIPProcessor(ProcessorMixin):
|
| 26 |
+
r"""
|
| 27 |
+
Constructs a CLIP processor which wraps a CLIP image processor and a CLIP tokenizer into a single processor.
|
| 28 |
+
|
| 29 |
+
[`CLIPProcessor`] offers all the functionalities of [`CLIPImageProcessor`] and [`CLIPTokenizerFast`]. See the
|
| 30 |
+
[`~CLIPProcessor.__call__`] and [`~CLIPProcessor.decode`] for more information.
|
| 31 |
+
|
| 32 |
+
Args:
|
| 33 |
+
image_processor ([`CLIPImageProcessor`], *optional*):
|
| 34 |
+
The image processor is a required input.
|
| 35 |
+
tokenizer ([`CLIPTokenizerFast`], *optional*):
|
| 36 |
+
The tokenizer is a required input.
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
attributes = ["image_processor", "tokenizer"]
|
| 40 |
+
image_processor_class = ("CLIPImageProcessor", "CLIPImageProcessorFast")
|
| 41 |
+
tokenizer_class = ("CLIPTokenizer", "CLIPTokenizerFast")
|
| 42 |
+
|
| 43 |
+
def __init__(self, image_processor=None, tokenizer=None, **kwargs):
|
| 44 |
+
feature_extractor = None
|
| 45 |
+
if "feature_extractor" in kwargs:
|
| 46 |
+
warnings.warn(
|
| 47 |
+
"The `feature_extractor` argument is deprecated and will be removed in v5, use `image_processor`"
|
| 48 |
+
" instead.",
|
| 49 |
+
FutureWarning,
|
| 50 |
+
)
|
| 51 |
+
feature_extractor = kwargs.pop("feature_extractor")
|
| 52 |
+
|
| 53 |
+
image_processor = image_processor if image_processor is not None else feature_extractor
|
| 54 |
+
if image_processor is None:
|
| 55 |
+
raise ValueError("You need to specify an `image_processor`.")
|
| 56 |
+
if tokenizer is None:
|
| 57 |
+
raise ValueError("You need to specify a `tokenizer`.")
|
| 58 |
+
|
| 59 |
+
super().__init__(image_processor, tokenizer)
|
| 60 |
+
|
| 61 |
+
def __call__(self, text=None, images=None, return_tensors=None, **kwargs):
|
| 62 |
+
"""
|
| 63 |
+
Main method to prepare for the model one or several sequences(s) and image(s). This method forwards the `text`
|
| 64 |
+
and `kwargs` arguments to CLIPTokenizerFast's [`~CLIPTokenizerFast.__call__`] if `text` is not `None` to encode
|
| 65 |
+
the text. To prepare the image(s), this method forwards the `images` and `kwrags` arguments to
|
| 66 |
+
CLIPImageProcessor's [`~CLIPImageProcessor.__call__`] if `images` is not `None`. Please refer to the docstring
|
| 67 |
+
of the above two methods for more information.
|
| 68 |
+
|
| 69 |
+
Args:
|
| 70 |
+
text (`str`, `List[str]`, `List[List[str]]`):
|
| 71 |
+
The sequence or batch of sequences to be encoded. Each sequence can be a string or a list of strings
|
| 72 |
+
(pretokenized string). If the sequences are provided as list of strings (pretokenized), you must set
|
| 73 |
+
`is_split_into_words=True` (to lift the ambiguity with a batch of sequences).
|
| 74 |
+
images (`PIL.Image.Image`, `np.ndarray`, `torch.Tensor`, `List[PIL.Image.Image]`, `List[np.ndarray]`, `List[torch.Tensor]`):
|
| 75 |
+
The image or batch of images to be prepared. Each image can be a PIL image, NumPy array or PyTorch
|
| 76 |
+
tensor. Both channels-first and channels-last formats are supported.
|
| 77 |
+
|
| 78 |
+
return_tensors (`str` or [`~utils.TensorType`], *optional*):
|
| 79 |
+
If set, will return tensors of a particular framework. Acceptable values are:
|
| 80 |
+
|
| 81 |
+
- `'tf'`: Return TensorFlow `tf.constant` objects.
|
| 82 |
+
- `'pt'`: Return PyTorch `torch.Tensor` objects.
|
| 83 |
+
- `'np'`: Return NumPy `np.ndarray` objects.
|
| 84 |
+
- `'jax'`: Return JAX `jnp.ndarray` objects.
|
| 85 |
+
|
| 86 |
+
Returns:
|
| 87 |
+
[`BatchEncoding`]: A [`BatchEncoding`] with the following fields:
|
| 88 |
+
|
| 89 |
+
- **input_ids** -- List of token ids to be fed to a model. Returned when `text` is not `None`.
|
| 90 |
+
- **attention_mask** -- List of indices specifying which tokens should be attended to by the model (when
|
| 91 |
+
`return_attention_mask=True` or if *"attention_mask"* is in `self.model_input_names` and if `text` is not
|
| 92 |
+
`None`).
|
| 93 |
+
- **pixel_values** -- Pixel values to be fed to a model. Returned when `images` is not `None`.
|
| 94 |
+
"""
|
| 95 |
+
tokenizer_kwargs, image_processor_kwargs = {}, {}
|
| 96 |
+
if kwargs:
|
| 97 |
+
tokenizer_kwargs = {k: v for k, v in kwargs.items() if k not in self.image_processor._valid_processor_keys}
|
| 98 |
+
image_processor_kwargs = {
|
| 99 |
+
k: v for k, v in kwargs.items() if k in self.image_processor._valid_processor_keys
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
if text is None and images is None:
|
| 103 |
+
raise ValueError("You have to specify either text or images. Both cannot be none.")
|
| 104 |
+
|
| 105 |
+
if text is not None:
|
| 106 |
+
encoding = self.tokenizer(text, return_tensors=return_tensors, **tokenizer_kwargs)
|
| 107 |
+
|
| 108 |
+
if images is not None:
|
| 109 |
+
image_features = self.image_processor(images, return_tensors=return_tensors, **image_processor_kwargs)
|
| 110 |
+
|
| 111 |
+
if text is not None and images is not None:
|
| 112 |
+
encoding["pixel_values"] = image_features.pixel_values
|
| 113 |
+
return encoding
|
| 114 |
+
elif text is not None:
|
| 115 |
+
return encoding
|
| 116 |
+
else:
|
| 117 |
+
return BatchEncoding(data=dict(**image_features), tensor_type=return_tensors)
|
| 118 |
+
|
| 119 |
+
def batch_decode(self, *args, **kwargs):
|
| 120 |
+
"""
|
| 121 |
+
This method forwards all its arguments to CLIPTokenizerFast's [`~PreTrainedTokenizer.batch_decode`]. Please
|
| 122 |
+
refer to the docstring of this method for more information.
|
| 123 |
+
"""
|
| 124 |
+
return self.tokenizer.batch_decode(*args, **kwargs)
|
| 125 |
+
|
| 126 |
+
def decode(self, *args, **kwargs):
|
| 127 |
+
"""
|
| 128 |
+
This method forwards all its arguments to CLIPTokenizerFast's [`~PreTrainedTokenizer.decode`]. Please refer to
|
| 129 |
+
the docstring of this method for more information.
|
| 130 |
+
"""
|
| 131 |
+
return self.tokenizer.decode(*args, **kwargs)
|
| 132 |
+
|
| 133 |
+
@property
|
| 134 |
+
def model_input_names(self):
|
| 135 |
+
tokenizer_input_names = self.tokenizer.model_input_names
|
| 136 |
+
image_processor_input_names = self.image_processor.model_input_names
|
| 137 |
+
return list(dict.fromkeys(tokenizer_input_names + image_processor_input_names))
|
| 138 |
+
|
| 139 |
+
@property
|
| 140 |
+
def feature_extractor_class(self):
|
| 141 |
+
warnings.warn(
|
| 142 |
+
"`feature_extractor_class` is deprecated and will be removed in v5. Use `image_processor_class` instead.",
|
| 143 |
+
FutureWarning,
|
| 144 |
+
)
|
| 145 |
+
return self.image_processor_class
|
| 146 |
+
|
| 147 |
+
@property
|
| 148 |
+
def feature_extractor(self):
|
| 149 |
+
warnings.warn(
|
| 150 |
+
"`feature_extractor` is deprecated and will be removed in v5. Use `image_processor` instead.",
|
| 151 |
+
FutureWarning,
|
| 152 |
+
)
|
| 153 |
+
return self.image_processor
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
__all__ = ["CLIPProcessor"]
|
lib/python3.12/site-packages/transformers/models/clip/tokenization_clip.py
ADDED
|
@@ -0,0 +1,519 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2021 The Open AI Team Authors and The HuggingFace Inc. team.
|
| 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 |
+
"""Tokenization classes for CLIP."""
|
| 16 |
+
|
| 17 |
+
import json
|
| 18 |
+
import os
|
| 19 |
+
import unicodedata
|
| 20 |
+
from functools import lru_cache
|
| 21 |
+
from typing import List, Optional, Tuple
|
| 22 |
+
|
| 23 |
+
import regex as re
|
| 24 |
+
|
| 25 |
+
from ...tokenization_utils import AddedToken, PreTrainedTokenizer, _is_control, _is_punctuation, _is_whitespace
|
| 26 |
+
from ...utils import logging
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
logger = logging.get_logger(__name__)
|
| 30 |
+
|
| 31 |
+
VOCAB_FILES_NAMES = {
|
| 32 |
+
"vocab_file": "vocab.json",
|
| 33 |
+
"merges_file": "merges.txt",
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
@lru_cache()
|
| 38 |
+
def bytes_to_unicode():
|
| 39 |
+
"""
|
| 40 |
+
Returns list of utf-8 byte and a mapping to unicode strings. We specifically avoids mapping to whitespace/control
|
| 41 |
+
characters the bpe code barfs on.
|
| 42 |
+
|
| 43 |
+
The reversible bpe codes work on unicode strings. This means you need a large # of unicode characters in your vocab
|
| 44 |
+
if you want to avoid UNKs. When you're at something like a 10B token dataset you end up needing around 5K for
|
| 45 |
+
decent coverage. This is a significant percentage of your normal, say, 32K bpe vocab. To avoid that, we want lookup
|
| 46 |
+
tables between utf-8 bytes and unicode strings.
|
| 47 |
+
"""
|
| 48 |
+
bs = (
|
| 49 |
+
list(range(ord("!"), ord("~") + 1)) + list(range(ord("¡"), ord("¬") + 1)) + list(range(ord("®"), ord("ÿ") + 1))
|
| 50 |
+
)
|
| 51 |
+
cs = bs[:]
|
| 52 |
+
n = 0
|
| 53 |
+
for b in range(2**8):
|
| 54 |
+
if b not in bs:
|
| 55 |
+
bs.append(b)
|
| 56 |
+
cs.append(2**8 + n)
|
| 57 |
+
n += 1
|
| 58 |
+
cs = [chr(n) for n in cs]
|
| 59 |
+
return dict(zip(bs, cs))
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def get_pairs(word):
|
| 63 |
+
"""
|
| 64 |
+
Return set of symbol pairs in a word.
|
| 65 |
+
|
| 66 |
+
Word is represented as tuple of symbols (symbols being variable-length strings).
|
| 67 |
+
"""
|
| 68 |
+
pairs = set()
|
| 69 |
+
prev_char = word[0]
|
| 70 |
+
for char in word[1:]:
|
| 71 |
+
pairs.add((prev_char, char))
|
| 72 |
+
prev_char = char
|
| 73 |
+
return pairs
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def whitespace_clean(text):
|
| 77 |
+
text = re.sub(r"\s+", " ", text)
|
| 78 |
+
text = text.strip()
|
| 79 |
+
return text
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
# Copied from transformers.models.bert.tokenization_bert.whitespace_tokenize
|
| 83 |
+
def whitespace_tokenize(text):
|
| 84 |
+
"""Runs basic whitespace cleaning and splitting on a piece of text."""
|
| 85 |
+
text = text.strip()
|
| 86 |
+
if not text:
|
| 87 |
+
return []
|
| 88 |
+
tokens = text.split()
|
| 89 |
+
return tokens
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
# Copied from transformers.models.bert.tokenization_bert.BasicTokenizer
|
| 93 |
+
class BasicTokenizer:
|
| 94 |
+
"""
|
| 95 |
+
Constructs a BasicTokenizer that will run basic tokenization (punctuation splitting, lower casing, etc.).
|
| 96 |
+
|
| 97 |
+
Args:
|
| 98 |
+
do_lower_case (`bool`, *optional*, defaults to `True`):
|
| 99 |
+
Whether or not to lowercase the input when tokenizing.
|
| 100 |
+
never_split (`Iterable`, *optional*):
|
| 101 |
+
Collection of tokens which will never be split during tokenization. Only has an effect when
|
| 102 |
+
`do_basic_tokenize=True`
|
| 103 |
+
tokenize_chinese_chars (`bool`, *optional*, defaults to `True`):
|
| 104 |
+
Whether or not to tokenize Chinese characters.
|
| 105 |
+
|
| 106 |
+
This should likely be deactivated for Japanese (see this
|
| 107 |
+
[issue](https://github.com/huggingface/transformers/issues/328)).
|
| 108 |
+
strip_accents (`bool`, *optional*):
|
| 109 |
+
Whether or not to strip all accents. If this option is not specified, then it will be determined by the
|
| 110 |
+
value for `lowercase` (as in the original BERT).
|
| 111 |
+
do_split_on_punc (`bool`, *optional*, defaults to `True`):
|
| 112 |
+
In some instances we want to skip the basic punctuation splitting so that later tokenization can capture
|
| 113 |
+
the full context of the words, such as contractions.
|
| 114 |
+
"""
|
| 115 |
+
|
| 116 |
+
def __init__(
|
| 117 |
+
self,
|
| 118 |
+
do_lower_case=True,
|
| 119 |
+
never_split=None,
|
| 120 |
+
tokenize_chinese_chars=True,
|
| 121 |
+
strip_accents=None,
|
| 122 |
+
do_split_on_punc=True,
|
| 123 |
+
):
|
| 124 |
+
if never_split is None:
|
| 125 |
+
never_split = []
|
| 126 |
+
self.do_lower_case = do_lower_case
|
| 127 |
+
self.never_split = set(never_split)
|
| 128 |
+
self.tokenize_chinese_chars = tokenize_chinese_chars
|
| 129 |
+
self.strip_accents = strip_accents
|
| 130 |
+
self.do_split_on_punc = do_split_on_punc
|
| 131 |
+
|
| 132 |
+
def tokenize(self, text, never_split=None):
|
| 133 |
+
"""
|
| 134 |
+
Basic Tokenization of a piece of text. For sub-word tokenization, see WordPieceTokenizer.
|
| 135 |
+
|
| 136 |
+
Args:
|
| 137 |
+
never_split (`List[str]`, *optional*)
|
| 138 |
+
Kept for backward compatibility purposes. Now implemented directly at the base class level (see
|
| 139 |
+
[`PreTrainedTokenizer.tokenize`]) List of token not to split.
|
| 140 |
+
"""
|
| 141 |
+
# union() returns a new set by concatenating the two sets.
|
| 142 |
+
never_split = self.never_split.union(set(never_split)) if never_split else self.never_split
|
| 143 |
+
text = self._clean_text(text)
|
| 144 |
+
|
| 145 |
+
# This was added on November 1st, 2018 for the multilingual and Chinese
|
| 146 |
+
# models. This is also applied to the English models now, but it doesn't
|
| 147 |
+
# matter since the English models were not trained on any Chinese data
|
| 148 |
+
# and generally don't have any Chinese data in them (there are Chinese
|
| 149 |
+
# characters in the vocabulary because Wikipedia does have some Chinese
|
| 150 |
+
# words in the English Wikipedia.).
|
| 151 |
+
if self.tokenize_chinese_chars:
|
| 152 |
+
text = self._tokenize_chinese_chars(text)
|
| 153 |
+
# prevents treating the same character with different unicode codepoints as different characters
|
| 154 |
+
unicode_normalized_text = unicodedata.normalize("NFC", text)
|
| 155 |
+
orig_tokens = whitespace_tokenize(unicode_normalized_text)
|
| 156 |
+
split_tokens = []
|
| 157 |
+
for token in orig_tokens:
|
| 158 |
+
if token not in never_split:
|
| 159 |
+
if self.do_lower_case:
|
| 160 |
+
token = token.lower()
|
| 161 |
+
if self.strip_accents is not False:
|
| 162 |
+
token = self._run_strip_accents(token)
|
| 163 |
+
elif self.strip_accents:
|
| 164 |
+
token = self._run_strip_accents(token)
|
| 165 |
+
split_tokens.extend(self._run_split_on_punc(token, never_split))
|
| 166 |
+
|
| 167 |
+
output_tokens = whitespace_tokenize(" ".join(split_tokens))
|
| 168 |
+
return output_tokens
|
| 169 |
+
|
| 170 |
+
def _run_strip_accents(self, text):
|
| 171 |
+
"""Strips accents from a piece of text."""
|
| 172 |
+
text = unicodedata.normalize("NFD", text)
|
| 173 |
+
output = []
|
| 174 |
+
for char in text:
|
| 175 |
+
cat = unicodedata.category(char)
|
| 176 |
+
if cat == "Mn":
|
| 177 |
+
continue
|
| 178 |
+
output.append(char)
|
| 179 |
+
return "".join(output)
|
| 180 |
+
|
| 181 |
+
def _run_split_on_punc(self, text, never_split=None):
|
| 182 |
+
"""Splits punctuation on a piece of text."""
|
| 183 |
+
if not self.do_split_on_punc or (never_split is not None and text in never_split):
|
| 184 |
+
return [text]
|
| 185 |
+
chars = list(text)
|
| 186 |
+
i = 0
|
| 187 |
+
start_new_word = True
|
| 188 |
+
output = []
|
| 189 |
+
while i < len(chars):
|
| 190 |
+
char = chars[i]
|
| 191 |
+
if _is_punctuation(char):
|
| 192 |
+
output.append([char])
|
| 193 |
+
start_new_word = True
|
| 194 |
+
else:
|
| 195 |
+
if start_new_word:
|
| 196 |
+
output.append([])
|
| 197 |
+
start_new_word = False
|
| 198 |
+
output[-1].append(char)
|
| 199 |
+
i += 1
|
| 200 |
+
|
| 201 |
+
return ["".join(x) for x in output]
|
| 202 |
+
|
| 203 |
+
def _tokenize_chinese_chars(self, text):
|
| 204 |
+
"""Adds whitespace around any CJK character."""
|
| 205 |
+
output = []
|
| 206 |
+
for char in text:
|
| 207 |
+
cp = ord(char)
|
| 208 |
+
if self._is_chinese_char(cp):
|
| 209 |
+
output.append(" ")
|
| 210 |
+
output.append(char)
|
| 211 |
+
output.append(" ")
|
| 212 |
+
else:
|
| 213 |
+
output.append(char)
|
| 214 |
+
return "".join(output)
|
| 215 |
+
|
| 216 |
+
def _is_chinese_char(self, cp):
|
| 217 |
+
"""Checks whether CP is the codepoint of a CJK character."""
|
| 218 |
+
# This defines a "chinese character" as anything in the CJK Unicode block:
|
| 219 |
+
# https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block)
|
| 220 |
+
#
|
| 221 |
+
# Note that the CJK Unicode block is NOT all Japanese and Korean characters,
|
| 222 |
+
# despite its name. The modern Korean Hangul alphabet is a different block,
|
| 223 |
+
# as is Japanese Hiragana and Katakana. Those alphabets are used to write
|
| 224 |
+
# space-separated words, so they are not treated specially and handled
|
| 225 |
+
# like the all of the other languages.
|
| 226 |
+
if (
|
| 227 |
+
(cp >= 0x4E00 and cp <= 0x9FFF)
|
| 228 |
+
or (cp >= 0x3400 and cp <= 0x4DBF) #
|
| 229 |
+
or (cp >= 0x20000 and cp <= 0x2A6DF) #
|
| 230 |
+
or (cp >= 0x2A700 and cp <= 0x2B73F) #
|
| 231 |
+
or (cp >= 0x2B740 and cp <= 0x2B81F) #
|
| 232 |
+
or (cp >= 0x2B820 and cp <= 0x2CEAF) #
|
| 233 |
+
or (cp >= 0xF900 and cp <= 0xFAFF)
|
| 234 |
+
or (cp >= 0x2F800 and cp <= 0x2FA1F) #
|
| 235 |
+
): #
|
| 236 |
+
return True
|
| 237 |
+
|
| 238 |
+
return False
|
| 239 |
+
|
| 240 |
+
def _clean_text(self, text):
|
| 241 |
+
"""Performs invalid character removal and whitespace cleanup on text."""
|
| 242 |
+
output = []
|
| 243 |
+
for char in text:
|
| 244 |
+
cp = ord(char)
|
| 245 |
+
if cp == 0 or cp == 0xFFFD or _is_control(char):
|
| 246 |
+
continue
|
| 247 |
+
if _is_whitespace(char):
|
| 248 |
+
output.append(" ")
|
| 249 |
+
else:
|
| 250 |
+
output.append(char)
|
| 251 |
+
return "".join(output)
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
class CLIPTokenizer(PreTrainedTokenizer):
|
| 255 |
+
"""
|
| 256 |
+
Construct a CLIP tokenizer. Based on byte-level Byte-Pair-Encoding.
|
| 257 |
+
|
| 258 |
+
This tokenizer inherits from [`PreTrainedTokenizer`] which contains most of the main methods. Users should refer to
|
| 259 |
+
this superclass for more information regarding those methods.
|
| 260 |
+
|
| 261 |
+
Args:
|
| 262 |
+
vocab_file (`str`):
|
| 263 |
+
Path to the vocabulary file.
|
| 264 |
+
merges_file (`str`):
|
| 265 |
+
Path to the merges file.
|
| 266 |
+
errors (`str`, *optional*, defaults to `"replace"`):
|
| 267 |
+
Paradigm to follow when decoding bytes to UTF-8. See
|
| 268 |
+
[bytes.decode](https://docs.python.org/3/library/stdtypes.html#bytes.decode) for more information.
|
| 269 |
+
unk_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 270 |
+
The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
|
| 271 |
+
token instead.
|
| 272 |
+
bos_token (`str`, *optional*, defaults to `"<|startoftext|>"`):
|
| 273 |
+
The beginning of sequence token.
|
| 274 |
+
eos_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 275 |
+
The end of sequence token.
|
| 276 |
+
pad_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 277 |
+
The token used for padding, for example when batching sequences of different lengths.
|
| 278 |
+
"""
|
| 279 |
+
|
| 280 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 281 |
+
model_input_names = ["input_ids", "attention_mask"]
|
| 282 |
+
|
| 283 |
+
def __init__(
|
| 284 |
+
self,
|
| 285 |
+
vocab_file,
|
| 286 |
+
merges_file,
|
| 287 |
+
errors="replace",
|
| 288 |
+
unk_token="<|endoftext|>",
|
| 289 |
+
bos_token="<|startoftext|>",
|
| 290 |
+
eos_token="<|endoftext|>",
|
| 291 |
+
pad_token="<|endoftext|>", # hack to enable padding
|
| 292 |
+
**kwargs,
|
| 293 |
+
):
|
| 294 |
+
bos_token = AddedToken(bos_token, lstrip=False, rstrip=False) if isinstance(bos_token, str) else bos_token
|
| 295 |
+
eos_token = AddedToken(eos_token, lstrip=False, rstrip=False) if isinstance(eos_token, str) else eos_token
|
| 296 |
+
unk_token = AddedToken(unk_token, lstrip=False, rstrip=False) if isinstance(unk_token, str) else unk_token
|
| 297 |
+
try:
|
| 298 |
+
import ftfy
|
| 299 |
+
|
| 300 |
+
self.fix_text = ftfy.fix_text
|
| 301 |
+
except ImportError:
|
| 302 |
+
logger.info("ftfy or spacy is not installed using custom BasicTokenizer instead of ftfy.")
|
| 303 |
+
self.nlp = BasicTokenizer(strip_accents=False, do_split_on_punc=False)
|
| 304 |
+
self.fix_text = None
|
| 305 |
+
|
| 306 |
+
with open(vocab_file, encoding="utf-8") as vocab_handle:
|
| 307 |
+
self.encoder = json.load(vocab_handle)
|
| 308 |
+
self.decoder = {v: k for k, v in self.encoder.items()}
|
| 309 |
+
self.errors = errors # how to handle errors in decoding
|
| 310 |
+
self.byte_encoder = bytes_to_unicode()
|
| 311 |
+
self.byte_decoder = {v: k for k, v in self.byte_encoder.items()}
|
| 312 |
+
with open(merges_file, encoding="utf-8") as merges_handle:
|
| 313 |
+
bpe_merges = merges_handle.read().strip().split("\n")[1 : 49152 - 256 - 2 + 1]
|
| 314 |
+
bpe_merges = [tuple(merge.split()) for merge in bpe_merges]
|
| 315 |
+
self.bpe_ranks = dict(zip(bpe_merges, range(len(bpe_merges))))
|
| 316 |
+
self.cache = {"<|startoftext|>": "<|startoftext|>", "<|endoftext|>": "<|endoftext|>"}
|
| 317 |
+
|
| 318 |
+
self.pat = re.compile(
|
| 319 |
+
r"""<\|startoftext\|>|<\|endoftext\|>|'s|'t|'re|'ve|'m|'ll|'d|[\p{L}]+|[\p{N}]|[^\s\p{L}\p{N}]+""",
|
| 320 |
+
re.IGNORECASE,
|
| 321 |
+
)
|
| 322 |
+
|
| 323 |
+
super().__init__(
|
| 324 |
+
errors=errors,
|
| 325 |
+
unk_token=unk_token,
|
| 326 |
+
bos_token=bos_token,
|
| 327 |
+
eos_token=eos_token,
|
| 328 |
+
pad_token=pad_token,
|
| 329 |
+
**kwargs,
|
| 330 |
+
)
|
| 331 |
+
|
| 332 |
+
@property
|
| 333 |
+
def vocab_size(self):
|
| 334 |
+
return len(self.encoder)
|
| 335 |
+
|
| 336 |
+
def get_vocab(self):
|
| 337 |
+
return dict(self.encoder, **self.added_tokens_encoder)
|
| 338 |
+
|
| 339 |
+
def build_inputs_with_special_tokens(
|
| 340 |
+
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
| 341 |
+
) -> List[int]:
|
| 342 |
+
"""
|
| 343 |
+
Build model inputs from a sequence or a pair of sequence for sequence classification tasks by concatenating and
|
| 344 |
+
adding special tokens. A CLIP sequence has the following format:
|
| 345 |
+
|
| 346 |
+
- single sequence: `<|startoftext|> X <|endoftext|>`
|
| 347 |
+
|
| 348 |
+
Pairs of sequences are not the expected use case, but they will be handled without a separator.
|
| 349 |
+
|
| 350 |
+
Args:
|
| 351 |
+
token_ids_0 (`List[int]`):
|
| 352 |
+
List of IDs to which the special tokens will be added.
|
| 353 |
+
token_ids_1 (`List[int]`, *optional*):
|
| 354 |
+
Optional second list of IDs for sequence pairs.
|
| 355 |
+
|
| 356 |
+
Returns:
|
| 357 |
+
`List[int]`: List of [input IDs](../glossary#input-ids) with the appropriate special tokens.
|
| 358 |
+
"""
|
| 359 |
+
bos_token = [self.bos_token_id]
|
| 360 |
+
eos_token = [self.eos_token_id]
|
| 361 |
+
|
| 362 |
+
if token_ids_1 is None:
|
| 363 |
+
return bos_token + token_ids_0 + eos_token
|
| 364 |
+
return bos_token + token_ids_0 + eos_token + eos_token + token_ids_1 + eos_token
|
| 365 |
+
|
| 366 |
+
def get_special_tokens_mask(
|
| 367 |
+
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None, already_has_special_tokens: bool = False
|
| 368 |
+
) -> List[int]:
|
| 369 |
+
"""
|
| 370 |
+
Retrieve sequence ids from a token list that has no special tokens added. This method is called when adding
|
| 371 |
+
special tokens using the tokenizer `prepare_for_model` method.
|
| 372 |
+
|
| 373 |
+
Args:
|
| 374 |
+
token_ids_0 (`List[int]`):
|
| 375 |
+
List of IDs.
|
| 376 |
+
token_ids_1 (`List[int]`, *optional*):
|
| 377 |
+
Optional second list of IDs for sequence pairs.
|
| 378 |
+
already_has_special_tokens (`bool`, *optional*, defaults to `False`):
|
| 379 |
+
Whether or not the token list is already formatted with special tokens for the model.
|
| 380 |
+
|
| 381 |
+
Returns:
|
| 382 |
+
`List[int]`: A list of integers in the range [0, 1]: 1 for a special token, 0 for a sequence token.
|
| 383 |
+
"""
|
| 384 |
+
|
| 385 |
+
if already_has_special_tokens:
|
| 386 |
+
return super().get_special_tokens_mask(
|
| 387 |
+
token_ids_0=token_ids_0, token_ids_1=token_ids_1, already_has_special_tokens=True
|
| 388 |
+
)
|
| 389 |
+
|
| 390 |
+
if token_ids_1 is None:
|
| 391 |
+
return [1] + ([0] * len(token_ids_0)) + [1]
|
| 392 |
+
return [1] + ([0] * len(token_ids_0)) + [1] + [1] + ([0] * len(token_ids_1)) + [1]
|
| 393 |
+
|
| 394 |
+
def create_token_type_ids_from_sequences(
|
| 395 |
+
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
| 396 |
+
) -> List[int]:
|
| 397 |
+
"""
|
| 398 |
+
Create a mask from the two sequences passed. CLIP does not make use of token type ids, therefore a list of
|
| 399 |
+
zeros is returned.
|
| 400 |
+
|
| 401 |
+
Args:
|
| 402 |
+
token_ids_0 (`List[int]`):
|
| 403 |
+
List of IDs.
|
| 404 |
+
token_ids_1 (`List[int]`, *optional*):
|
| 405 |
+
Optional second list of IDs for sequence pairs.
|
| 406 |
+
|
| 407 |
+
Returns:
|
| 408 |
+
`List[int]`: List of zeros.
|
| 409 |
+
"""
|
| 410 |
+
bos_token = [self.bos_token_id]
|
| 411 |
+
eos_token = [self.eos_token_id]
|
| 412 |
+
|
| 413 |
+
if token_ids_1 is None:
|
| 414 |
+
return len(bos_token + token_ids_0 + eos_token) * [0]
|
| 415 |
+
return len(bos_token + token_ids_0 + eos_token + eos_token + token_ids_1 + eos_token) * [0]
|
| 416 |
+
|
| 417 |
+
def bpe(self, token):
|
| 418 |
+
if token in self.cache:
|
| 419 |
+
return self.cache[token]
|
| 420 |
+
word = tuple(token[:-1]) + (token[-1] + "</w>",)
|
| 421 |
+
pairs = get_pairs(word)
|
| 422 |
+
|
| 423 |
+
if not pairs:
|
| 424 |
+
return token + "</w>"
|
| 425 |
+
|
| 426 |
+
while True:
|
| 427 |
+
bigram = min(pairs, key=lambda pair: self.bpe_ranks.get(pair, float("inf")))
|
| 428 |
+
if bigram not in self.bpe_ranks:
|
| 429 |
+
break
|
| 430 |
+
first, second = bigram
|
| 431 |
+
new_word = []
|
| 432 |
+
i = 0
|
| 433 |
+
while i < len(word):
|
| 434 |
+
try:
|
| 435 |
+
j = word.index(first, i)
|
| 436 |
+
except ValueError:
|
| 437 |
+
new_word.extend(word[i:])
|
| 438 |
+
break
|
| 439 |
+
else:
|
| 440 |
+
new_word.extend(word[i:j])
|
| 441 |
+
i = j
|
| 442 |
+
|
| 443 |
+
if word[i] == first and i < len(word) - 1 and word[i + 1] == second:
|
| 444 |
+
new_word.append(first + second)
|
| 445 |
+
i += 2
|
| 446 |
+
else:
|
| 447 |
+
new_word.append(word[i])
|
| 448 |
+
i += 1
|
| 449 |
+
new_word = tuple(new_word)
|
| 450 |
+
word = new_word
|
| 451 |
+
if len(word) == 1:
|
| 452 |
+
break
|
| 453 |
+
else:
|
| 454 |
+
pairs = get_pairs(word)
|
| 455 |
+
word = " ".join(word)
|
| 456 |
+
self.cache[token] = word
|
| 457 |
+
return word
|
| 458 |
+
|
| 459 |
+
def _tokenize(self, text):
|
| 460 |
+
"""Tokenize a string."""
|
| 461 |
+
bpe_tokens = []
|
| 462 |
+
if self.fix_text is None:
|
| 463 |
+
text = " ".join(self.nlp.tokenize(text))
|
| 464 |
+
else:
|
| 465 |
+
text = whitespace_clean(self.fix_text(text)).lower()
|
| 466 |
+
|
| 467 |
+
for token in re.findall(self.pat, text):
|
| 468 |
+
token = "".join(
|
| 469 |
+
self.byte_encoder[b] for b in token.encode("utf-8")
|
| 470 |
+
) # Maps all our bytes to unicode strings, avoiding control tokens of the BPE (spaces in our case)
|
| 471 |
+
bpe_tokens.extend(bpe_token for bpe_token in self.bpe(token).split(" "))
|
| 472 |
+
return bpe_tokens
|
| 473 |
+
|
| 474 |
+
def _convert_token_to_id(self, token):
|
| 475 |
+
"""Converts a token (str) in an id using the vocab."""
|
| 476 |
+
return self.encoder.get(token, self.encoder.get(self.unk_token))
|
| 477 |
+
|
| 478 |
+
def _convert_id_to_token(self, index):
|
| 479 |
+
"""Converts an index (integer) in a token (str) using the vocab."""
|
| 480 |
+
return self.decoder.get(index)
|
| 481 |
+
|
| 482 |
+
def convert_tokens_to_string(self, tokens):
|
| 483 |
+
"""Converts a sequence of tokens (string) in a single string."""
|
| 484 |
+
text = "".join(tokens)
|
| 485 |
+
byte_array = bytearray([self.byte_decoder[c] for c in text])
|
| 486 |
+
text = byte_array.decode("utf-8", errors=self.errors).replace("</w>", " ").strip()
|
| 487 |
+
return text
|
| 488 |
+
|
| 489 |
+
def save_vocabulary(self, save_directory: str, filename_prefix: Optional[str] = None) -> Tuple[str]:
|
| 490 |
+
if not os.path.isdir(save_directory):
|
| 491 |
+
logger.error("Vocabulary path ({}) should be a directory".format(save_directory))
|
| 492 |
+
return
|
| 493 |
+
vocab_file = os.path.join(
|
| 494 |
+
save_directory, (filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["vocab_file"]
|
| 495 |
+
)
|
| 496 |
+
merge_file = os.path.join(
|
| 497 |
+
save_directory, (filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["merges_file"]
|
| 498 |
+
)
|
| 499 |
+
|
| 500 |
+
with open(vocab_file, "w", encoding="utf-8") as f:
|
| 501 |
+
f.write(json.dumps(self.encoder, indent=2, sort_keys=True, ensure_ascii=False) + "\n")
|
| 502 |
+
|
| 503 |
+
index = 0
|
| 504 |
+
with open(merge_file, "w", encoding="utf-8") as writer:
|
| 505 |
+
writer.write("#version: 0.2\n")
|
| 506 |
+
for bpe_tokens, token_index in sorted(self.bpe_ranks.items(), key=lambda kv: kv[1]):
|
| 507 |
+
if index != token_index:
|
| 508 |
+
logger.warning(
|
| 509 |
+
"Saving vocabulary to {}: BPE merge indices are not consecutive."
|
| 510 |
+
" Please check that the tokenizer is not corrupted!".format(merge_file)
|
| 511 |
+
)
|
| 512 |
+
index = token_index
|
| 513 |
+
writer.write(" ".join(bpe_tokens) + "\n")
|
| 514 |
+
index += 1
|
| 515 |
+
|
| 516 |
+
return vocab_file, merge_file
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
__all__ = ["CLIPTokenizer"]
|
lib/python3.12/site-packages/transformers/models/clip/tokenization_clip_fast.py
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2021 The Open AI Team Authors and The HuggingFace Inc. team.
|
| 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 |
+
"""Tokenization classes for OpenAI GPT."""
|
| 16 |
+
|
| 17 |
+
from typing import List, Optional, Tuple
|
| 18 |
+
|
| 19 |
+
from tokenizers import pre_tokenizers
|
| 20 |
+
|
| 21 |
+
from ...tokenization_utils_fast import PreTrainedTokenizerFast
|
| 22 |
+
from ...utils import logging
|
| 23 |
+
from .tokenization_clip import CLIPTokenizer
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
logger = logging.get_logger(__name__)
|
| 27 |
+
|
| 28 |
+
VOCAB_FILES_NAMES = {"vocab_file": "vocab.json", "merges_file": "merges.txt", "tokenizer_file": "tokenizer.json"}
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class CLIPTokenizerFast(PreTrainedTokenizerFast):
|
| 32 |
+
"""
|
| 33 |
+
Construct a "fast" CLIP tokenizer (backed by HuggingFace's *tokenizers* library). Based on byte-level
|
| 34 |
+
Byte-Pair-Encoding.
|
| 35 |
+
|
| 36 |
+
This tokenizer inherits from [`PreTrainedTokenizerFast`] which contains most of the main methods. Users should
|
| 37 |
+
refer to this superclass for more information regarding those methods.
|
| 38 |
+
|
| 39 |
+
Args:
|
| 40 |
+
vocab_file (`str`, *optional*):
|
| 41 |
+
Path to the vocabulary file.
|
| 42 |
+
merges_file (`str`, *optional*):
|
| 43 |
+
Path to the merges file.
|
| 44 |
+
tokenizer_file (`str`, *optional*):
|
| 45 |
+
The path to a tokenizer file to use instead of the vocab file.
|
| 46 |
+
unk_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 47 |
+
The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
|
| 48 |
+
token instead.
|
| 49 |
+
bos_token (`str`, *optional*, defaults to `"<|startoftext|>"`):
|
| 50 |
+
The beginning of sequence token.
|
| 51 |
+
eos_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 52 |
+
The end of sequence token.
|
| 53 |
+
pad_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 54 |
+
The token used for padding, for example when batching sequences of different lengths.
|
| 55 |
+
"""
|
| 56 |
+
|
| 57 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 58 |
+
model_input_names = ["input_ids", "attention_mask"]
|
| 59 |
+
slow_tokenizer_class = CLIPTokenizer
|
| 60 |
+
|
| 61 |
+
def __init__(
|
| 62 |
+
self,
|
| 63 |
+
vocab_file=None,
|
| 64 |
+
merges_file=None,
|
| 65 |
+
tokenizer_file=None,
|
| 66 |
+
unk_token="<|endoftext|>",
|
| 67 |
+
bos_token="<|startoftext|>",
|
| 68 |
+
eos_token="<|endoftext|>",
|
| 69 |
+
pad_token="<|endoftext|>", # hack to enable padding
|
| 70 |
+
**kwargs,
|
| 71 |
+
):
|
| 72 |
+
super().__init__(
|
| 73 |
+
vocab_file,
|
| 74 |
+
merges_file,
|
| 75 |
+
tokenizer_file=tokenizer_file,
|
| 76 |
+
unk_token=unk_token,
|
| 77 |
+
bos_token=bos_token,
|
| 78 |
+
eos_token=eos_token,
|
| 79 |
+
pad_token=pad_token,
|
| 80 |
+
**kwargs,
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
if not isinstance(self.backend_tokenizer.pre_tokenizer, pre_tokenizers.Sequence):
|
| 84 |
+
raise ValueError(
|
| 85 |
+
"The `backend_tokenizer` provided does not match the expected format. The CLIP tokenizer has been"
|
| 86 |
+
" heavily modified from transformers version 4.17.0. You need to convert the tokenizer you are using"
|
| 87 |
+
" to be compatible with this version.The easiest way to do so is"
|
| 88 |
+
' `CLIPTokenizerFast.from_pretrained("path_to_local_folder_or_hub_repo, from_slow=True)`. If you want'
|
| 89 |
+
" to use your existing tokenizer, you will have to revert to a version prior to 4.17.0 of"
|
| 90 |
+
" transformers."
|
| 91 |
+
)
|
| 92 |
+
self._wrap_decode_method_backend_tokenizer()
|
| 93 |
+
|
| 94 |
+
# Very ugly hack to enable padding to have a correct decoding see https://github.com/huggingface/tokenizers/issues/872
|
| 95 |
+
def _wrap_decode_method_backend_tokenizer(self):
|
| 96 |
+
orig_decode_method = self.backend_tokenizer.decode
|
| 97 |
+
|
| 98 |
+
## define this as a local variable to avoid circular reference
|
| 99 |
+
## See: https://github.com/huggingface/transformers/issues/30930
|
| 100 |
+
end_of_word_suffix = self.backend_tokenizer.model.end_of_word_suffix
|
| 101 |
+
|
| 102 |
+
def new_decode_method(*args, **kwargs):
|
| 103 |
+
text = orig_decode_method(*args, **kwargs)
|
| 104 |
+
text = text.replace(end_of_word_suffix, " ").strip()
|
| 105 |
+
return text
|
| 106 |
+
|
| 107 |
+
self.backend_tokenizer.decode = new_decode_method
|
| 108 |
+
|
| 109 |
+
def build_inputs_with_special_tokens(
|
| 110 |
+
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
| 111 |
+
) -> List[int]:
|
| 112 |
+
"""
|
| 113 |
+
Build model inputs from a sequence or a pair of sequence for sequence classification tasks by concatenating and
|
| 114 |
+
adding special tokens. A CLIP sequence has the following format:
|
| 115 |
+
|
| 116 |
+
- single sequence: `<|startoftext|> X <|endoftext|>`
|
| 117 |
+
|
| 118 |
+
Pairs of sequences are not the expected use case, but they will be handled without a separator.
|
| 119 |
+
|
| 120 |
+
Args:
|
| 121 |
+
token_ids_0 (`List[int]`):
|
| 122 |
+
List of IDs to which the special tokens will be added.
|
| 123 |
+
token_ids_1 (`List[int]`, *optional*):
|
| 124 |
+
Optional second list of IDs for sequence pairs.
|
| 125 |
+
|
| 126 |
+
Returns:
|
| 127 |
+
`List[int]`: List of [input IDs](../glossary#input-ids) with the appropriate special tokens.
|
| 128 |
+
"""
|
| 129 |
+
bos_token = [self.bos_token_id]
|
| 130 |
+
eos_token = [self.eos_token_id]
|
| 131 |
+
|
| 132 |
+
if token_ids_1 is None:
|
| 133 |
+
return bos_token + token_ids_0 + eos_token
|
| 134 |
+
return bos_token + token_ids_0 + eos_token + eos_token + token_ids_1 + eos_token
|
| 135 |
+
|
| 136 |
+
def create_token_type_ids_from_sequences(
|
| 137 |
+
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
| 138 |
+
) -> List[int]:
|
| 139 |
+
"""
|
| 140 |
+
Create a mask from the two sequences passed. CLIP does not make use of token type ids, therefore a list of
|
| 141 |
+
zeros is returned.
|
| 142 |
+
|
| 143 |
+
Args:
|
| 144 |
+
token_ids_0 (`List[int]`):
|
| 145 |
+
List of IDs.
|
| 146 |
+
token_ids_1 (`List[int]`, *optional*):
|
| 147 |
+
Optional second list of IDs for sequence pairs.
|
| 148 |
+
|
| 149 |
+
Returns:
|
| 150 |
+
`List[int]`: List of zeros.
|
| 151 |
+
"""
|
| 152 |
+
bos_token = [self.bos_token_id]
|
| 153 |
+
eos_token = [self.eos_token_id]
|
| 154 |
+
|
| 155 |
+
if token_ids_1 is None:
|
| 156 |
+
return len(bos_token + token_ids_0 + eos_token) * [0]
|
| 157 |
+
return len(bos_token + token_ids_0 + eos_token + eos_token + token_ids_1 + eos_token) * [0]
|
| 158 |
+
|
| 159 |
+
def save_vocabulary(self, save_directory: str, filename_prefix: Optional[str] = None) -> Tuple[str]:
|
| 160 |
+
files = self._tokenizer.model.save(save_directory, name=filename_prefix)
|
| 161 |
+
return tuple(files)
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
__all__ = ["CLIPTokenizerFast"]
|
lib/python3.12/site-packages/transformers/models/colpali/__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_colpali import *
|
| 22 |
+
from .modeling_colpali import *
|
| 23 |
+
from .processing_colpali 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__)
|