Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- third_party/transformers/src/transformers/__init__.py +852 -0
- third_party/transformers/src/transformers/debug_utils.py +348 -0
- third_party/transformers/src/transformers/distributed/__init__.py +33 -0
- third_party/transformers/src/transformers/distributed/configuration_utils.py +110 -0
- third_party/transformers/src/transformers/hyperparameter_search.py +123 -0
- third_party/transformers/src/transformers/masking_utils.py +1608 -0
- third_party/transformers/src/transformers/model_debugging_utils.py +455 -0
- third_party/transformers/src/transformers/modeling_flash_attention_utils.py +807 -0
- third_party/transformers/src/transformers/modeling_layers.py +288 -0
- third_party/transformers/src/transformers/models/__init__.py +472 -0
- third_party/transformers/src/transformers/models/beit/__init__.py +29 -0
- third_party/transformers/src/transformers/models/beit/configuration_beit.py +117 -0
- third_party/transformers/src/transformers/models/beit/convert_beit_unilm_to_pytorch.py +375 -0
- third_party/transformers/src/transformers/models/beit/image_processing_beit.py +228 -0
- third_party/transformers/src/transformers/models/beit/image_processing_pil_beit.py +209 -0
- third_party/transformers/src/transformers/models/beit/modeling_beit.py +1470 -0
- third_party/transformers/src/transformers/models/cohere2/__init__.py +27 -0
- third_party/transformers/src/transformers/models/cohere2/configuration_cohere2.py +107 -0
- third_party/transformers/src/transformers/models/cohere_asr/__init__.py +30 -0
- third_party/transformers/src/transformers/models/cohere_asr/configuration_cohere_asr.py +101 -0
- third_party/transformers/src/transformers/models/cohere_asr/feature_extraction_cohere_asr.py +374 -0
- third_party/transformers/src/transformers/models/cohere_asr/modeling_cohere_asr.py +658 -0
- third_party/transformers/src/transformers/models/cohere_asr/modular_cohere_asr.py +525 -0
- third_party/transformers/src/transformers/models/cohere_asr/processing_cohere_asr.py +188 -0
- third_party/transformers/src/transformers/models/deepseek_vl_hybrid/__init__.py +30 -0
- third_party/transformers/src/transformers/models/deepseek_vl_hybrid/configuration_deepseek_vl_hybrid.py +92 -0
- third_party/transformers/src/transformers/models/deepseek_vl_hybrid/convert_deepseek_vl_hybrid_weights_to_hf.py +386 -0
- third_party/transformers/src/transformers/models/deepseek_vl_hybrid/image_processing_deepseek_vl_hybrid.py +297 -0
- third_party/transformers/src/transformers/models/deepseek_vl_hybrid/image_processing_pil_deepseek_vl_hybrid.py +261 -0
- third_party/transformers/src/transformers/models/deepseek_vl_hybrid/modeling_deepseek_vl_hybrid.py +539 -0
- third_party/transformers/src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.py +787 -0
- third_party/transformers/src/transformers/models/deepseek_vl_hybrid/processing_deepseek_vl_hybrid.py +119 -0
- third_party/transformers/src/transformers/models/diffllama/__init__.py +27 -0
- third_party/transformers/src/transformers/models/diffllama/configuration_diffllama.py +80 -0
- third_party/transformers/src/transformers/models/diffllama/modeling_diffllama.py +753 -0
- third_party/transformers/src/transformers/models/diffllama/modular_diffllama.py +417 -0
- third_party/transformers/src/transformers/models/encodec/__init__.py +28 -0
- third_party/transformers/src/transformers/models/encodec/configuration_encodec.py +155 -0
- third_party/transformers/src/transformers/models/encodec/convert_encodec_checkpoint_to_pytorch.py +364 -0
- third_party/transformers/src/transformers/models/encodec/feature_extraction_encodec.py +205 -0
- third_party/transformers/src/transformers/models/encodec/modeling_encodec.py +822 -0
- third_party/transformers/src/transformers/models/herbert/__init__.py +26 -0
- third_party/transformers/src/transformers/models/herbert/tokenization_herbert.py +111 -0
- third_party/transformers/src/transformers/models/maskformer/__init__.py +32 -0
- third_party/transformers/src/transformers/models/maskformer/configuration_maskformer.py +226 -0
- third_party/transformers/src/transformers/models/maskformer/configuration_maskformer_swin.py +82 -0
- third_party/transformers/src/transformers/models/maskformer/convert_maskformer_original_pytorch_checkpoint_to_pytorch.py +724 -0
- third_party/transformers/src/transformers/models/maskformer/convert_maskformer_resnet_to_pytorch.py +403 -0
- third_party/transformers/src/transformers/models/maskformer/convert_maskformer_swin_to_pytorch.py +346 -0
- third_party/transformers/src/transformers/models/maskformer/image_processing_maskformer.py +806 -0
third_party/transformers/src/transformers/__init__.py
ADDED
|
@@ -0,0 +1,852 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
# When adding a new object to this init, remember to add it twice: once inside the `_import_structure` dictionary and
|
| 16 |
+
# once inside the `if TYPE_CHECKING` branch. The `TYPE_CHECKING` should have import statements as usual, but they are
|
| 17 |
+
# only there for type checking. The `_import_structure` is a dictionary submodule to list of object names, and is used
|
| 18 |
+
# to defer the actual importing for when the objects are requested. This way `import transformers` provides the names
|
| 19 |
+
# in the namespace without actually importing anything (and especially none of the backends).
|
| 20 |
+
|
| 21 |
+
__version__ = "5.6.0.dev0"
|
| 22 |
+
|
| 23 |
+
import importlib
|
| 24 |
+
import sys
|
| 25 |
+
import types
|
| 26 |
+
from pathlib import Path
|
| 27 |
+
from typing import TYPE_CHECKING
|
| 28 |
+
|
| 29 |
+
# Check the dependencies satisfy the minimal versions required.
|
| 30 |
+
from . import dependency_versions_check
|
| 31 |
+
from .utils import (
|
| 32 |
+
OptionalDependencyNotAvailable,
|
| 33 |
+
_LazyModule,
|
| 34 |
+
is_essentia_available,
|
| 35 |
+
is_g2p_en_available,
|
| 36 |
+
is_librosa_available,
|
| 37 |
+
is_mistral_common_available,
|
| 38 |
+
is_mlx_available,
|
| 39 |
+
is_numba_available,
|
| 40 |
+
is_pretty_midi_available,
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# Note: the following symbols are deliberately exported with `as`
|
| 44 |
+
# so that mypy, pylint or other static linters can recognize them,
|
| 45 |
+
# given that they are not exported using `__all__` in this file.
|
| 46 |
+
from .utils import is_bitsandbytes_available as is_bitsandbytes_available
|
| 47 |
+
from .utils import is_scipy_available as is_scipy_available
|
| 48 |
+
from .utils import is_sentencepiece_available as is_sentencepiece_available
|
| 49 |
+
from .utils import is_speech_available as is_speech_available
|
| 50 |
+
from .utils import is_timm_available as is_timm_available
|
| 51 |
+
from .utils import is_tokenizers_available as is_tokenizers_available
|
| 52 |
+
from .utils import is_torch_available as is_torch_available
|
| 53 |
+
from .utils import is_torchaudio_available as is_torchaudio_available
|
| 54 |
+
from .utils import is_torchvision_available as is_torchvision_available
|
| 55 |
+
from .utils import is_vision_available as is_vision_available
|
| 56 |
+
from .utils import logging as logging
|
| 57 |
+
from .utils.import_utils import define_import_structure
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
logger = logging.get_logger(__name__) # pylint: disable=invalid-name
|
| 61 |
+
|
| 62 |
+
# Base objects, independent of any specific backend
|
| 63 |
+
_import_structure = {
|
| 64 |
+
"audio_utils": [],
|
| 65 |
+
"cli": [],
|
| 66 |
+
"configuration_utils": ["PreTrainedConfig", "PretrainedConfig"],
|
| 67 |
+
"convert_slow_tokenizers_checkpoints_to_fast": [],
|
| 68 |
+
"data": [
|
| 69 |
+
"DataProcessor",
|
| 70 |
+
"InputExample",
|
| 71 |
+
"InputFeatures",
|
| 72 |
+
"SingleSentenceClassificationProcessor",
|
| 73 |
+
"SquadExample",
|
| 74 |
+
"SquadFeatures",
|
| 75 |
+
"SquadV1Processor",
|
| 76 |
+
"SquadV2Processor",
|
| 77 |
+
"glue_compute_metrics",
|
| 78 |
+
"glue_convert_examples_to_features",
|
| 79 |
+
"glue_output_modes",
|
| 80 |
+
"glue_processors",
|
| 81 |
+
"glue_tasks_num_labels",
|
| 82 |
+
"squad_convert_examples_to_features",
|
| 83 |
+
"xnli_compute_metrics",
|
| 84 |
+
"xnli_output_modes",
|
| 85 |
+
"xnli_processors",
|
| 86 |
+
"xnli_tasks_num_labels",
|
| 87 |
+
],
|
| 88 |
+
"data.data_collator": [
|
| 89 |
+
"DataCollator",
|
| 90 |
+
"DataCollatorForLanguageModeling",
|
| 91 |
+
"DataCollatorForMultipleChoice",
|
| 92 |
+
"DataCollatorForPermutationLanguageModeling",
|
| 93 |
+
"DataCollatorForSeq2Seq",
|
| 94 |
+
"DataCollatorForSOP",
|
| 95 |
+
"DataCollatorForTokenClassification",
|
| 96 |
+
"DataCollatorForWholeWordMask",
|
| 97 |
+
"DataCollatorWithFlattening",
|
| 98 |
+
"DataCollatorWithPadding",
|
| 99 |
+
"DefaultDataCollator",
|
| 100 |
+
"default_data_collator",
|
| 101 |
+
],
|
| 102 |
+
"data.metrics": [],
|
| 103 |
+
"data.processors": [],
|
| 104 |
+
"debug_utils": [],
|
| 105 |
+
"dependency_versions_check": [],
|
| 106 |
+
"dependency_versions_table": [],
|
| 107 |
+
"dynamic_module_utils": [],
|
| 108 |
+
"feature_extraction_sequence_utils": ["SequenceFeatureExtractor"],
|
| 109 |
+
"feature_extraction_utils": ["BatchFeature", "FeatureExtractionMixin"],
|
| 110 |
+
"file_utils": [],
|
| 111 |
+
"generation": [
|
| 112 |
+
"AsyncTextIteratorStreamer",
|
| 113 |
+
"CompileConfig",
|
| 114 |
+
"ContinuousBatchingConfig",
|
| 115 |
+
"GenerationConfig",
|
| 116 |
+
"TextIteratorStreamer",
|
| 117 |
+
"TextStreamer",
|
| 118 |
+
"WatermarkingConfig",
|
| 119 |
+
],
|
| 120 |
+
"hf_argparser": ["HfArgumentParser"],
|
| 121 |
+
"hyperparameter_search": [],
|
| 122 |
+
"image_processing_utils_fast": [],
|
| 123 |
+
"image_transforms": [],
|
| 124 |
+
"integrations": [
|
| 125 |
+
"is_clearml_available",
|
| 126 |
+
"is_comet_available",
|
| 127 |
+
"is_dvclive_available",
|
| 128 |
+
"is_neptune_available",
|
| 129 |
+
"is_optuna_available",
|
| 130 |
+
"is_ray_available",
|
| 131 |
+
"is_ray_tune_available",
|
| 132 |
+
"is_swanlab_available",
|
| 133 |
+
"is_tensorboard_available",
|
| 134 |
+
"is_trackio_available",
|
| 135 |
+
"is_wandb_available",
|
| 136 |
+
],
|
| 137 |
+
"loss": [],
|
| 138 |
+
"pipelines": [
|
| 139 |
+
"AnyToAnyPipeline",
|
| 140 |
+
"AudioClassificationPipeline",
|
| 141 |
+
"AutomaticSpeechRecognitionPipeline",
|
| 142 |
+
"CsvPipelineDataFormat",
|
| 143 |
+
"DepthEstimationPipeline",
|
| 144 |
+
"DocumentQuestionAnsweringPipeline",
|
| 145 |
+
"FeatureExtractionPipeline",
|
| 146 |
+
"FillMaskPipeline",
|
| 147 |
+
"ImageClassificationPipeline",
|
| 148 |
+
"ImageFeatureExtractionPipeline",
|
| 149 |
+
"ImageSegmentationPipeline",
|
| 150 |
+
"ImageTextToTextPipeline",
|
| 151 |
+
"JsonPipelineDataFormat",
|
| 152 |
+
"KeypointMatchingPipeline",
|
| 153 |
+
"MaskGenerationPipeline",
|
| 154 |
+
"NerPipeline",
|
| 155 |
+
"ObjectDetectionPipeline",
|
| 156 |
+
"PipedPipelineDataFormat",
|
| 157 |
+
"Pipeline",
|
| 158 |
+
"PipelineDataFormat",
|
| 159 |
+
"TableQuestionAnsweringPipeline",
|
| 160 |
+
"TextClassificationPipeline",
|
| 161 |
+
"TextGenerationPipeline",
|
| 162 |
+
"TextToAudioPipeline",
|
| 163 |
+
"TokenClassificationPipeline",
|
| 164 |
+
"VideoClassificationPipeline",
|
| 165 |
+
"ZeroShotAudioClassificationPipeline",
|
| 166 |
+
"ZeroShotClassificationPipeline",
|
| 167 |
+
"ZeroShotImageClassificationPipeline",
|
| 168 |
+
"ZeroShotObjectDetectionPipeline",
|
| 169 |
+
"pipeline",
|
| 170 |
+
],
|
| 171 |
+
"processing_utils": [
|
| 172 |
+
"AudioKwargs",
|
| 173 |
+
"ImagesKwargs",
|
| 174 |
+
"ProcessingKwargs",
|
| 175 |
+
"ProcessorMixin",
|
| 176 |
+
"TextKwargs",
|
| 177 |
+
"VideosKwargs",
|
| 178 |
+
],
|
| 179 |
+
"quantizers": [],
|
| 180 |
+
"testing_utils": [],
|
| 181 |
+
"tokenization_python": ["PreTrainedTokenizer", "PythonBackend"],
|
| 182 |
+
"tokenization_utils": [],
|
| 183 |
+
"tokenization_utils_base": [
|
| 184 |
+
"AddedToken",
|
| 185 |
+
"BatchEncoding",
|
| 186 |
+
"CharSpan",
|
| 187 |
+
"PreTrainedTokenizerBase",
|
| 188 |
+
"TokenSpan",
|
| 189 |
+
],
|
| 190 |
+
"tokenization_utils_fast": [],
|
| 191 |
+
"tokenization_utils_sentencepiece": ["SentencePieceBackend"],
|
| 192 |
+
"trainer_callback": [
|
| 193 |
+
"DefaultFlowCallback",
|
| 194 |
+
"EarlyStoppingCallback",
|
| 195 |
+
"PrinterCallback",
|
| 196 |
+
"ProgressCallback",
|
| 197 |
+
"TrainerCallback",
|
| 198 |
+
"TrainerControl",
|
| 199 |
+
"TrainerState",
|
| 200 |
+
],
|
| 201 |
+
"trainer_utils": [
|
| 202 |
+
"EvalPrediction",
|
| 203 |
+
"IntervalStrategy",
|
| 204 |
+
"SchedulerType",
|
| 205 |
+
"enable_full_determinism",
|
| 206 |
+
"set_seed",
|
| 207 |
+
],
|
| 208 |
+
"training_args": ["TrainingArguments"],
|
| 209 |
+
"training_args_seq2seq": ["Seq2SeqTrainingArguments"],
|
| 210 |
+
"utils": [
|
| 211 |
+
"CONFIG_NAME",
|
| 212 |
+
"MODEL_CARD_NAME",
|
| 213 |
+
"SPIECE_UNDERLINE",
|
| 214 |
+
"WEIGHTS_NAME",
|
| 215 |
+
"TensorType",
|
| 216 |
+
"add_end_docstrings",
|
| 217 |
+
"add_start_docstrings",
|
| 218 |
+
"is_apex_available",
|
| 219 |
+
"is_av_available",
|
| 220 |
+
"is_bitsandbytes_available",
|
| 221 |
+
"is_datasets_available",
|
| 222 |
+
"is_faiss_available",
|
| 223 |
+
"is_matplotlib_available",
|
| 224 |
+
"is_mlx_available",
|
| 225 |
+
"is_phonemizer_available",
|
| 226 |
+
"is_psutil_available",
|
| 227 |
+
"is_py3nvml_available",
|
| 228 |
+
"is_pyctcdecode_available",
|
| 229 |
+
"is_sacremoses_available",
|
| 230 |
+
"is_scipy_available",
|
| 231 |
+
"is_sentencepiece_available",
|
| 232 |
+
"is_sklearn_available",
|
| 233 |
+
"is_speech_available",
|
| 234 |
+
"is_timm_available",
|
| 235 |
+
"is_tokenizers_available",
|
| 236 |
+
"is_torch_available",
|
| 237 |
+
"is_torch_hpu_available",
|
| 238 |
+
"is_torch_mlu_available",
|
| 239 |
+
"is_torch_musa_available",
|
| 240 |
+
"is_torch_neuroncore_available",
|
| 241 |
+
"is_torch_npu_available",
|
| 242 |
+
"is_torchvision_available",
|
| 243 |
+
"is_torch_xla_available",
|
| 244 |
+
"is_torch_xpu_available",
|
| 245 |
+
"is_vision_available",
|
| 246 |
+
"logging",
|
| 247 |
+
],
|
| 248 |
+
"utils.import_utils": ["requires_backends"],
|
| 249 |
+
"utils.kernel_config": ["KernelConfig"],
|
| 250 |
+
"utils.quantization_config": [
|
| 251 |
+
"AqlmConfig",
|
| 252 |
+
"AutoRoundConfig",
|
| 253 |
+
"AwqConfig",
|
| 254 |
+
"BitNetQuantConfig",
|
| 255 |
+
"BitsAndBytesConfig",
|
| 256 |
+
"CompressedTensorsConfig",
|
| 257 |
+
"EetqConfig",
|
| 258 |
+
"FbgemmFp8Config",
|
| 259 |
+
"FineGrainedFP8Config",
|
| 260 |
+
"FourOverSixConfig",
|
| 261 |
+
"FPQuantConfig",
|
| 262 |
+
"GPTQConfig",
|
| 263 |
+
"HiggsConfig",
|
| 264 |
+
"HqqConfig",
|
| 265 |
+
"MetalConfig",
|
| 266 |
+
"Mxfp4Config",
|
| 267 |
+
"QuantoConfig",
|
| 268 |
+
"QuarkConfig",
|
| 269 |
+
"SinqConfig",
|
| 270 |
+
"SpQRConfig",
|
| 271 |
+
"TorchAoConfig",
|
| 272 |
+
"VptqConfig",
|
| 273 |
+
],
|
| 274 |
+
"video_utils": [],
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
# tokenizers-backed objects
|
| 278 |
+
try:
|
| 279 |
+
if not is_tokenizers_available():
|
| 280 |
+
raise OptionalDependencyNotAvailable()
|
| 281 |
+
except OptionalDependencyNotAvailable:
|
| 282 |
+
from .utils import dummy_tokenizers_objects
|
| 283 |
+
|
| 284 |
+
_import_structure["utils.dummy_tokenizers_objects"] = [
|
| 285 |
+
name for name in dir(dummy_tokenizers_objects) if not name.startswith("_")
|
| 286 |
+
]
|
| 287 |
+
else:
|
| 288 |
+
# Fast tokenizers structure
|
| 289 |
+
_import_structure["tokenization_utils_tokenizers"] = [
|
| 290 |
+
"PreTrainedTokenizerFast",
|
| 291 |
+
"TokenizersBackend",
|
| 292 |
+
]
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
try:
|
| 296 |
+
if not (is_sentencepiece_available() and is_tokenizers_available()):
|
| 297 |
+
raise OptionalDependencyNotAvailable()
|
| 298 |
+
except OptionalDependencyNotAvailable:
|
| 299 |
+
from .utils import dummy_sentencepiece_and_tokenizers_objects
|
| 300 |
+
|
| 301 |
+
_import_structure["utils.dummy_sentencepiece_and_tokenizers_objects"] = [
|
| 302 |
+
name for name in dir(dummy_sentencepiece_and_tokenizers_objects) if not name.startswith("_")
|
| 303 |
+
]
|
| 304 |
+
else:
|
| 305 |
+
_import_structure["convert_slow_tokenizer"] = [
|
| 306 |
+
"SLOW_TO_FAST_CONVERTERS",
|
| 307 |
+
"convert_slow_tokenizer",
|
| 308 |
+
]
|
| 309 |
+
|
| 310 |
+
try:
|
| 311 |
+
if not (is_mistral_common_available()):
|
| 312 |
+
raise OptionalDependencyNotAvailable()
|
| 313 |
+
except OptionalDependencyNotAvailable:
|
| 314 |
+
from .utils import dummy_mistral_common_objects
|
| 315 |
+
|
| 316 |
+
_import_structure["utils.dummy_mistral_common_objects"] = [
|
| 317 |
+
name for name in dir(dummy_mistral_common_objects) if not name.startswith("_")
|
| 318 |
+
]
|
| 319 |
+
else:
|
| 320 |
+
_import_structure["tokenization_mistral_common"] = ["MistralCommonBackend"]
|
| 321 |
+
|
| 322 |
+
# Vision-specific objects
|
| 323 |
+
try:
|
| 324 |
+
if not is_vision_available():
|
| 325 |
+
raise OptionalDependencyNotAvailable()
|
| 326 |
+
except OptionalDependencyNotAvailable:
|
| 327 |
+
from .utils import dummy_vision_objects
|
| 328 |
+
|
| 329 |
+
_import_structure["utils.dummy_vision_objects"] = [
|
| 330 |
+
name for name in dir(dummy_vision_objects) if not name.startswith("_")
|
| 331 |
+
]
|
| 332 |
+
else:
|
| 333 |
+
_import_structure["image_processing_backends"] = ["PilBackend"]
|
| 334 |
+
_import_structure["image_processing_base"] = ["ImageProcessingMixin"]
|
| 335 |
+
_import_structure["image_processing_utils"] = ["BaseImageProcessor"]
|
| 336 |
+
_import_structure["image_utils"] = ["ImageFeatureExtractionMixin"]
|
| 337 |
+
|
| 338 |
+
try:
|
| 339 |
+
if not is_torchvision_available():
|
| 340 |
+
raise OptionalDependencyNotAvailable()
|
| 341 |
+
except OptionalDependencyNotAvailable:
|
| 342 |
+
from .utils import dummy_torchvision_objects
|
| 343 |
+
|
| 344 |
+
_import_structure["utils.dummy_torchvision_objects"] = [
|
| 345 |
+
name for name in dir(dummy_torchvision_objects) if not name.startswith("_")
|
| 346 |
+
]
|
| 347 |
+
else:
|
| 348 |
+
_import_structure.setdefault("image_processing_backends", [])
|
| 349 |
+
_import_structure["image_processing_backends"] += ["TorchvisionBackend"]
|
| 350 |
+
_import_structure["video_processing_utils"] = ["BaseVideoProcessor"]
|
| 351 |
+
|
| 352 |
+
# PyTorch-backed objects
|
| 353 |
+
try:
|
| 354 |
+
if not is_torch_available():
|
| 355 |
+
raise OptionalDependencyNotAvailable()
|
| 356 |
+
except OptionalDependencyNotAvailable:
|
| 357 |
+
from .utils import dummy_pt_objects
|
| 358 |
+
|
| 359 |
+
_import_structure["utils.dummy_pt_objects"] = [name for name in dir(dummy_pt_objects) if not name.startswith("_")]
|
| 360 |
+
else:
|
| 361 |
+
_import_structure["model_debugging_utils"] = [
|
| 362 |
+
"model_addition_debugger_context",
|
| 363 |
+
]
|
| 364 |
+
_import_structure["activations"] = []
|
| 365 |
+
_import_structure["cache_utils"] = [
|
| 366 |
+
"CacheLayerMixin",
|
| 367 |
+
"DynamicLayer",
|
| 368 |
+
"StaticLayer",
|
| 369 |
+
"StaticSlidingWindowLayer",
|
| 370 |
+
"QuantoQuantizedLayer",
|
| 371 |
+
"HQQQuantizedLayer",
|
| 372 |
+
"Cache",
|
| 373 |
+
"DynamicCache",
|
| 374 |
+
"EncoderDecoderCache",
|
| 375 |
+
"QuantizedCache",
|
| 376 |
+
"StaticCache",
|
| 377 |
+
]
|
| 378 |
+
_import_structure["data.datasets"] = [
|
| 379 |
+
"GlueDataset",
|
| 380 |
+
"GlueDataTrainingArguments",
|
| 381 |
+
"SquadDataset",
|
| 382 |
+
"SquadDataTrainingArguments",
|
| 383 |
+
]
|
| 384 |
+
_import_structure["generation"].extend(
|
| 385 |
+
[
|
| 386 |
+
"AlternatingCodebooksLogitsProcessor",
|
| 387 |
+
"BayesianDetectorConfig",
|
| 388 |
+
"BayesianDetectorModel",
|
| 389 |
+
"ClassifierFreeGuidanceLogitsProcessor",
|
| 390 |
+
"ContinuousBatchingManager",
|
| 391 |
+
"ContinuousMixin",
|
| 392 |
+
"EncoderNoRepeatNGramLogitsProcessor",
|
| 393 |
+
"EncoderRepetitionPenaltyLogitsProcessor",
|
| 394 |
+
"EosTokenCriteria",
|
| 395 |
+
"EpsilonLogitsWarper",
|
| 396 |
+
"MinPLogitsWarper",
|
| 397 |
+
"EtaLogitsWarper",
|
| 398 |
+
"ExponentialDecayLengthPenalty",
|
| 399 |
+
"ForcedBOSTokenLogitsProcessor",
|
| 400 |
+
"ForcedEOSTokenLogitsProcessor",
|
| 401 |
+
"GenerationMixin",
|
| 402 |
+
"InfNanRemoveLogitsProcessor",
|
| 403 |
+
"LogitNormalization",
|
| 404 |
+
"LogitsProcessor",
|
| 405 |
+
"LogitsProcessorList",
|
| 406 |
+
"MaxLengthCriteria",
|
| 407 |
+
"MaxTimeCriteria",
|
| 408 |
+
"MinLengthLogitsProcessor",
|
| 409 |
+
"MinNewTokensLengthLogitsProcessor",
|
| 410 |
+
"NoBadWordsLogitsProcessor",
|
| 411 |
+
"NoRepeatNGramLogitsProcessor",
|
| 412 |
+
"PrefixConstrainedLogitsProcessor",
|
| 413 |
+
"RepetitionPenaltyLogitsProcessor",
|
| 414 |
+
"SequenceBiasLogitsProcessor",
|
| 415 |
+
"StoppingCriteria",
|
| 416 |
+
"StoppingCriteriaList",
|
| 417 |
+
"StopStringCriteria",
|
| 418 |
+
"SuppressTokensAtBeginLogitsProcessor",
|
| 419 |
+
"SuppressTokensLogitsProcessor",
|
| 420 |
+
"SynthIDTextWatermarkDetector",
|
| 421 |
+
"SynthIDTextWatermarkingConfig",
|
| 422 |
+
"SynthIDTextWatermarkLogitsProcessor",
|
| 423 |
+
"TemperatureLogitsWarper",
|
| 424 |
+
"TopHLogitsWarper",
|
| 425 |
+
"TopKLogitsWarper",
|
| 426 |
+
"TopPLogitsWarper",
|
| 427 |
+
"TypicalLogitsWarper",
|
| 428 |
+
"UnbatchedClassifierFreeGuidanceLogitsProcessor",
|
| 429 |
+
"WatermarkDetector",
|
| 430 |
+
"WatermarkLogitsProcessor",
|
| 431 |
+
"WhisperTimeStampLogitsProcessor",
|
| 432 |
+
]
|
| 433 |
+
)
|
| 434 |
+
|
| 435 |
+
# PyTorch domain libraries integration
|
| 436 |
+
_import_structure["integrations.executorch"] = [
|
| 437 |
+
"TorchExportableModuleWithStaticCache",
|
| 438 |
+
"convert_and_export_with_cache",
|
| 439 |
+
]
|
| 440 |
+
|
| 441 |
+
_import_structure["core_model_loading"] = [
|
| 442 |
+
"Chunk",
|
| 443 |
+
"Concatenate",
|
| 444 |
+
"ConversionOps",
|
| 445 |
+
"MergeModulelist",
|
| 446 |
+
"PermuteForRope",
|
| 447 |
+
"SplitModulelist",
|
| 448 |
+
"WeightConverter",
|
| 449 |
+
]
|
| 450 |
+
_import_structure["modeling_flash_attention_utils"] = []
|
| 451 |
+
_import_structure["modeling_layers"] = ["GradientCheckpointingLayer"]
|
| 452 |
+
_import_structure["modeling_outputs"] = []
|
| 453 |
+
_import_structure["backbone_utils"] = ["BackboneConfigMixin", "BackboneMixin"]
|
| 454 |
+
_import_structure["modeling_rope_utils"] = ["ROPE_INIT_FUNCTIONS", "dynamic_rope_update", "RopeParameters"]
|
| 455 |
+
_import_structure["modeling_utils"] = ["PreTrainedModel", "AttentionInterface"]
|
| 456 |
+
_import_structure["masking_utils"] = ["AttentionMaskInterface"]
|
| 457 |
+
_import_structure["optimization"] = [
|
| 458 |
+
"Adafactor",
|
| 459 |
+
"get_constant_schedule",
|
| 460 |
+
"get_constant_schedule_with_warmup",
|
| 461 |
+
"get_cosine_schedule_with_warmup",
|
| 462 |
+
"get_cosine_with_hard_restarts_schedule_with_warmup",
|
| 463 |
+
"get_cosine_with_min_lr_schedule_with_warmup",
|
| 464 |
+
"get_cosine_with_min_lr_schedule_with_warmup_lr_rate",
|
| 465 |
+
"get_greedy_schedule",
|
| 466 |
+
"get_inverse_sqrt_schedule",
|
| 467 |
+
"get_linear_schedule_with_warmup",
|
| 468 |
+
"get_polynomial_decay_schedule_with_warmup",
|
| 469 |
+
"get_reduce_on_plateau_schedule",
|
| 470 |
+
"get_scheduler",
|
| 471 |
+
"get_wsd_schedule",
|
| 472 |
+
"GreedyLR",
|
| 473 |
+
]
|
| 474 |
+
_import_structure["pytorch_utils"] = ["Conv1D", "apply_chunking_to_forward"]
|
| 475 |
+
_import_structure["time_series_utils"] = []
|
| 476 |
+
_import_structure["trainer"] = ["Trainer"]
|
| 477 |
+
_import_structure["trainer_pt_utils"] = ["torch_distributed_zero_first"]
|
| 478 |
+
_import_structure["trainer_seq2seq"] = ["Seq2SeqTrainer"]
|
| 479 |
+
|
| 480 |
+
|
| 481 |
+
# Direct imports for type-checking
|
| 482 |
+
if TYPE_CHECKING:
|
| 483 |
+
# All modeling imports
|
| 484 |
+
# Models
|
| 485 |
+
from .backbone_utils import BackboneConfigMixin, BackboneMixin
|
| 486 |
+
from .cache_utils import Cache as Cache
|
| 487 |
+
from .cache_utils import DynamicCache as DynamicCache
|
| 488 |
+
from .cache_utils import DynamicLayer as DynamicLayer
|
| 489 |
+
from .cache_utils import EncoderDecoderCache as EncoderDecoderCache
|
| 490 |
+
from .cache_utils import HQQQuantizedLayer as HQQQuantizedLayer
|
| 491 |
+
from .cache_utils import QuantizedCache as QuantizedCache
|
| 492 |
+
from .cache_utils import QuantoQuantizedLayer as QuantoQuantizedLayer
|
| 493 |
+
from .cache_utils import StaticCache as StaticCache
|
| 494 |
+
from .cache_utils import StaticLayer as StaticLayer
|
| 495 |
+
from .cache_utils import StaticSlidingWindowLayer as StaticSlidingWindowLayer
|
| 496 |
+
from .configuration_utils import PreTrainedConfig as PreTrainedConfig
|
| 497 |
+
from .configuration_utils import PretrainedConfig as PretrainedConfig
|
| 498 |
+
from .convert_slow_tokenizer import SLOW_TO_FAST_CONVERTERS as SLOW_TO_FAST_CONVERTERS
|
| 499 |
+
from .convert_slow_tokenizer import convert_slow_tokenizer as convert_slow_tokenizer
|
| 500 |
+
from .core_model_loading import Chunk as Chunk
|
| 501 |
+
from .core_model_loading import Concatenate as Concatenate
|
| 502 |
+
from .core_model_loading import ConversionOps as ConversionOps
|
| 503 |
+
from .core_model_loading import MergeModulelist as MergeModulelist
|
| 504 |
+
from .core_model_loading import PermuteForRope as PermuteForRope
|
| 505 |
+
from .core_model_loading import SplitModulelist as SplitModulelist
|
| 506 |
+
from .core_model_loading import WeightConverter as WeightConverter
|
| 507 |
+
|
| 508 |
+
# Data
|
| 509 |
+
from .data import DataProcessor as DataProcessor
|
| 510 |
+
from .data import InputExample as InputExample
|
| 511 |
+
from .data import InputFeatures as InputFeatures
|
| 512 |
+
from .data import SingleSentenceClassificationProcessor as SingleSentenceClassificationProcessor
|
| 513 |
+
from .data import SquadExample as SquadExample
|
| 514 |
+
from .data import SquadFeatures as SquadFeatures
|
| 515 |
+
from .data import SquadV1Processor as SquadV1Processor
|
| 516 |
+
from .data import SquadV2Processor as SquadV2Processor
|
| 517 |
+
from .data import glue_compute_metrics as glue_compute_metrics
|
| 518 |
+
from .data import glue_convert_examples_to_features as glue_convert_examples_to_features
|
| 519 |
+
from .data import glue_output_modes as glue_output_modes
|
| 520 |
+
from .data import glue_processors as glue_processors
|
| 521 |
+
from .data import glue_tasks_num_labels as glue_tasks_num_labels
|
| 522 |
+
from .data import squad_convert_examples_to_features as squad_convert_examples_to_features
|
| 523 |
+
from .data import xnli_compute_metrics as xnli_compute_metrics
|
| 524 |
+
from .data import xnli_output_modes as xnli_output_modes
|
| 525 |
+
from .data import xnli_processors as xnli_processors
|
| 526 |
+
from .data import xnli_tasks_num_labels as xnli_tasks_num_labels
|
| 527 |
+
from .data.data_collator import DataCollator as DataCollator
|
| 528 |
+
from .data.data_collator import DataCollatorForLanguageModeling as DataCollatorForLanguageModeling
|
| 529 |
+
from .data.data_collator import DataCollatorForMultipleChoice as DataCollatorForMultipleChoice
|
| 530 |
+
from .data.data_collator import (
|
| 531 |
+
DataCollatorForPermutationLanguageModeling as DataCollatorForPermutationLanguageModeling,
|
| 532 |
+
)
|
| 533 |
+
from .data.data_collator import DataCollatorForSeq2Seq as DataCollatorForSeq2Seq
|
| 534 |
+
from .data.data_collator import DataCollatorForSOP as DataCollatorForSOP
|
| 535 |
+
from .data.data_collator import DataCollatorForTokenClassification as DataCollatorForTokenClassification
|
| 536 |
+
from .data.data_collator import DataCollatorForWholeWordMask as DataCollatorForWholeWordMask
|
| 537 |
+
from .data.data_collator import DataCollatorWithFlattening as DataCollatorWithFlattening
|
| 538 |
+
from .data.data_collator import DataCollatorWithPadding as DataCollatorWithPadding
|
| 539 |
+
from .data.data_collator import DefaultDataCollator as DefaultDataCollator
|
| 540 |
+
from .data.data_collator import default_data_collator as default_data_collator
|
| 541 |
+
from .data.datasets import GlueDataset as GlueDataset
|
| 542 |
+
from .data.datasets import GlueDataTrainingArguments as GlueDataTrainingArguments
|
| 543 |
+
from .data.datasets import SquadDataset as SquadDataset
|
| 544 |
+
from .data.datasets import SquadDataTrainingArguments as SquadDataTrainingArguments
|
| 545 |
+
from .feature_extraction_sequence_utils import SequenceFeatureExtractor as SequenceFeatureExtractor
|
| 546 |
+
|
| 547 |
+
# Feature Extractor
|
| 548 |
+
from .feature_extraction_utils import BatchFeature as BatchFeature
|
| 549 |
+
from .feature_extraction_utils import FeatureExtractionMixin as FeatureExtractionMixin
|
| 550 |
+
|
| 551 |
+
# Generation
|
| 552 |
+
from .generation import AlternatingCodebooksLogitsProcessor as AlternatingCodebooksLogitsProcessor
|
| 553 |
+
from .generation import AsyncTextIteratorStreamer as AsyncTextIteratorStreamer
|
| 554 |
+
from .generation import BayesianDetectorConfig as BayesianDetectorConfig
|
| 555 |
+
from .generation import BayesianDetectorModel as BayesianDetectorModel
|
| 556 |
+
from .generation import ClassifierFreeGuidanceLogitsProcessor as ClassifierFreeGuidanceLogitsProcessor
|
| 557 |
+
from .generation import CompileConfig as CompileConfig
|
| 558 |
+
from .generation import ContinuousBatchingConfig as ContinuousBatchingConfig
|
| 559 |
+
from .generation import ContinuousBatchingManager as ContinuousBatchingManager
|
| 560 |
+
from .generation import ContinuousMixin as ContinuousMixin
|
| 561 |
+
from .generation import EncoderNoRepeatNGramLogitsProcessor as EncoderNoRepeatNGramLogitsProcessor
|
| 562 |
+
from .generation import EncoderRepetitionPenaltyLogitsProcessor as EncoderRepetitionPenaltyLogitsProcessor
|
| 563 |
+
from .generation import EosTokenCriteria as EosTokenCriteria
|
| 564 |
+
from .generation import EpsilonLogitsWarper as EpsilonLogitsWarper
|
| 565 |
+
from .generation import EtaLogitsWarper as EtaLogitsWarper
|
| 566 |
+
from .generation import ExponentialDecayLengthPenalty as ExponentialDecayLengthPenalty
|
| 567 |
+
from .generation import ForcedBOSTokenLogitsProcessor as ForcedBOSTokenLogitsProcessor
|
| 568 |
+
from .generation import ForcedEOSTokenLogitsProcessor as ForcedEOSTokenLogitsProcessor
|
| 569 |
+
from .generation import GenerationConfig as GenerationConfig
|
| 570 |
+
from .generation import GenerationMixin as GenerationMixin
|
| 571 |
+
from .generation import InfNanRemoveLogitsProcessor as InfNanRemoveLogitsProcessor
|
| 572 |
+
from .generation import LogitNormalization as LogitNormalization
|
| 573 |
+
from .generation import LogitsProcessor as LogitsProcessor
|
| 574 |
+
from .generation import LogitsProcessorList as LogitsProcessorList
|
| 575 |
+
from .generation import MaxLengthCriteria as MaxLengthCriteria
|
| 576 |
+
from .generation import MaxTimeCriteria as MaxTimeCriteria
|
| 577 |
+
from .generation import MinLengthLogitsProcessor as MinLengthLogitsProcessor
|
| 578 |
+
from .generation import MinNewTokensLengthLogitsProcessor as MinNewTokensLengthLogitsProcessor
|
| 579 |
+
from .generation import MinPLogitsWarper as MinPLogitsWarper
|
| 580 |
+
from .generation import NoBadWordsLogitsProcessor as NoBadWordsLogitsProcessor
|
| 581 |
+
from .generation import NoRepeatNGramLogitsProcessor as NoRepeatNGramLogitsProcessor
|
| 582 |
+
from .generation import PrefixConstrainedLogitsProcessor as PrefixConstrainedLogitsProcessor
|
| 583 |
+
from .generation import RepetitionPenaltyLogitsProcessor as RepetitionPenaltyLogitsProcessor
|
| 584 |
+
from .generation import SequenceBiasLogitsProcessor as SequenceBiasLogitsProcessor
|
| 585 |
+
from .generation import StoppingCriteria as StoppingCriteria
|
| 586 |
+
from .generation import StoppingCriteriaList as StoppingCriteriaList
|
| 587 |
+
from .generation import StopStringCriteria as StopStringCriteria
|
| 588 |
+
from .generation import SuppressTokensAtBeginLogitsProcessor as SuppressTokensAtBeginLogitsProcessor
|
| 589 |
+
from .generation import SuppressTokensLogitsProcessor as SuppressTokensLogitsProcessor
|
| 590 |
+
from .generation import SynthIDTextWatermarkDetector as SynthIDTextWatermarkDetector
|
| 591 |
+
from .generation import SynthIDTextWatermarkingConfig as SynthIDTextWatermarkingConfig
|
| 592 |
+
from .generation import SynthIDTextWatermarkLogitsProcessor as SynthIDTextWatermarkLogitsProcessor
|
| 593 |
+
from .generation import TemperatureLogitsWarper as TemperatureLogitsWarper
|
| 594 |
+
from .generation import TextIteratorStreamer as TextIteratorStreamer
|
| 595 |
+
from .generation import TextStreamer as TextStreamer
|
| 596 |
+
from .generation import TopHLogitsWarper as TopHLogitsWarper
|
| 597 |
+
from .generation import TopKLogitsWarper as TopKLogitsWarper
|
| 598 |
+
from .generation import TopPLogitsWarper as TopPLogitsWarper
|
| 599 |
+
from .generation import TypicalLogitsWarper as TypicalLogitsWarper
|
| 600 |
+
from .generation import (
|
| 601 |
+
UnbatchedClassifierFreeGuidanceLogitsProcessor as UnbatchedClassifierFreeGuidanceLogitsProcessor,
|
| 602 |
+
)
|
| 603 |
+
from .generation import WatermarkDetector as WatermarkDetector
|
| 604 |
+
from .generation import WatermarkingConfig as WatermarkingConfig
|
| 605 |
+
from .generation import WatermarkLogitsProcessor as WatermarkLogitsProcessor
|
| 606 |
+
from .generation import WhisperTimeStampLogitsProcessor as WhisperTimeStampLogitsProcessor
|
| 607 |
+
from .hf_argparser import HfArgumentParser as HfArgumentParser
|
| 608 |
+
from .image_processing_backends import PilBackend as PilBackend
|
| 609 |
+
from .image_processing_backends import TorchvisionBackend as TorchvisionBackend
|
| 610 |
+
from .image_processing_base import ImageProcessingMixin as ImageProcessingMixin
|
| 611 |
+
from .image_processing_utils import BaseImageProcessor as BaseImageProcessor
|
| 612 |
+
from .image_utils import ImageFeatureExtractionMixin as ImageFeatureExtractionMixin
|
| 613 |
+
|
| 614 |
+
# Integrations
|
| 615 |
+
from .integrations import is_clearml_available as is_clearml_available
|
| 616 |
+
from .integrations import is_comet_available as is_comet_available
|
| 617 |
+
from .integrations import is_dvclive_available as is_dvclive_available
|
| 618 |
+
from .integrations import is_neptune_available as is_neptune_available
|
| 619 |
+
from .integrations import is_optuna_available as is_optuna_available
|
| 620 |
+
from .integrations import is_ray_available as is_ray_available
|
| 621 |
+
from .integrations import is_ray_tune_available as is_ray_tune_available
|
| 622 |
+
from .integrations import is_swanlab_available as is_swanlab_available
|
| 623 |
+
from .integrations import is_tensorboard_available as is_tensorboard_available
|
| 624 |
+
from .integrations import is_trackio_available as is_trackio_available
|
| 625 |
+
from .integrations import is_wandb_available as is_wandb_available
|
| 626 |
+
from .integrations.executorch import TorchExportableModuleWithStaticCache as TorchExportableModuleWithStaticCache
|
| 627 |
+
from .integrations.executorch import convert_and_export_with_cache as convert_and_export_with_cache
|
| 628 |
+
from .masking_utils import AttentionMaskInterface as AttentionMaskInterface
|
| 629 |
+
from .model_debugging_utils import model_addition_debugger_context as model_addition_debugger_context
|
| 630 |
+
from .modeling_layers import GradientCheckpointingLayer as GradientCheckpointingLayer
|
| 631 |
+
from .modeling_rope_utils import ROPE_INIT_FUNCTIONS as ROPE_INIT_FUNCTIONS
|
| 632 |
+
from .modeling_rope_utils import RopeParameters as RopeParameters
|
| 633 |
+
from .modeling_rope_utils import dynamic_rope_update as dynamic_rope_update
|
| 634 |
+
from .modeling_utils import AttentionInterface as AttentionInterface
|
| 635 |
+
from .modeling_utils import PreTrainedModel as PreTrainedModel
|
| 636 |
+
from .models import *
|
| 637 |
+
from .models.timm_wrapper import TimmWrapperImageProcessor as TimmWrapperImageProcessor
|
| 638 |
+
|
| 639 |
+
# Optimization
|
| 640 |
+
from .optimization import Adafactor as Adafactor
|
| 641 |
+
from .optimization import GreedyLR as GreedyLR
|
| 642 |
+
from .optimization import get_constant_schedule as get_constant_schedule
|
| 643 |
+
from .optimization import get_constant_schedule_with_warmup as get_constant_schedule_with_warmup
|
| 644 |
+
from .optimization import get_cosine_schedule_with_warmup as get_cosine_schedule_with_warmup
|
| 645 |
+
from .optimization import (
|
| 646 |
+
get_cosine_with_hard_restarts_schedule_with_warmup as get_cosine_with_hard_restarts_schedule_with_warmup,
|
| 647 |
+
)
|
| 648 |
+
from .optimization import (
|
| 649 |
+
get_cosine_with_min_lr_schedule_with_warmup as get_cosine_with_min_lr_schedule_with_warmup,
|
| 650 |
+
)
|
| 651 |
+
from .optimization import (
|
| 652 |
+
get_cosine_with_min_lr_schedule_with_warmup_lr_rate as get_cosine_with_min_lr_schedule_with_warmup_lr_rate,
|
| 653 |
+
)
|
| 654 |
+
from .optimization import get_greedy_schedule as get_greedy_schedule
|
| 655 |
+
from .optimization import get_inverse_sqrt_schedule as get_inverse_sqrt_schedule
|
| 656 |
+
from .optimization import get_linear_schedule_with_warmup as get_linear_schedule_with_warmup
|
| 657 |
+
from .optimization import get_polynomial_decay_schedule_with_warmup as get_polynomial_decay_schedule_with_warmup
|
| 658 |
+
from .optimization import get_scheduler as get_scheduler
|
| 659 |
+
from .optimization import get_wsd_schedule as get_wsd_schedule
|
| 660 |
+
|
| 661 |
+
# Pipelines
|
| 662 |
+
from .pipelines import AnyToAnyPipeline as AnyToAnyPipeline
|
| 663 |
+
from .pipelines import AudioClassificationPipeline as AudioClassificationPipeline
|
| 664 |
+
from .pipelines import AutomaticSpeechRecognitionPipeline as AutomaticSpeechRecognitionPipeline
|
| 665 |
+
from .pipelines import CsvPipelineDataFormat as CsvPipelineDataFormat
|
| 666 |
+
from .pipelines import DepthEstimationPipeline as DepthEstimationPipeline
|
| 667 |
+
from .pipelines import DocumentQuestionAnsweringPipeline as DocumentQuestionAnsweringPipeline
|
| 668 |
+
from .pipelines import FeatureExtractionPipeline as FeatureExtractionPipeline
|
| 669 |
+
from .pipelines import FillMaskPipeline as FillMaskPipeline
|
| 670 |
+
from .pipelines import ImageClassificationPipeline as ImageClassificationPipeline
|
| 671 |
+
from .pipelines import ImageFeatureExtractionPipeline as ImageFeatureExtractionPipeline
|
| 672 |
+
from .pipelines import ImageSegmentationPipeline as ImageSegmentationPipeline
|
| 673 |
+
from .pipelines import ImageTextToTextPipeline as ImageTextToTextPipeline
|
| 674 |
+
from .pipelines import JsonPipelineDataFormat as JsonPipelineDataFormat
|
| 675 |
+
from .pipelines import KeypointMatchingPipeline as KeypointMatchingPipeline
|
| 676 |
+
from .pipelines import MaskGenerationPipeline as MaskGenerationPipeline
|
| 677 |
+
from .pipelines import NerPipeline as NerPipeline
|
| 678 |
+
from .pipelines import ObjectDetectionPipeline as ObjectDetectionPipeline
|
| 679 |
+
from .pipelines import PipedPipelineDataFormat as PipedPipelineDataFormat
|
| 680 |
+
from .pipelines import Pipeline as Pipeline
|
| 681 |
+
from .pipelines import PipelineDataFormat as PipelineDataFormat
|
| 682 |
+
from .pipelines import TableQuestionAnsweringPipeline as TableQuestionAnsweringPipeline
|
| 683 |
+
from .pipelines import TextClassificationPipeline as TextClassificationPipeline
|
| 684 |
+
from .pipelines import TextGenerationPipeline as TextGenerationPipeline
|
| 685 |
+
from .pipelines import TextToAudioPipeline as TextToAudioPipeline
|
| 686 |
+
from .pipelines import TokenClassificationPipeline as TokenClassificationPipeline
|
| 687 |
+
from .pipelines import VideoClassificationPipeline as VideoClassificationPipeline
|
| 688 |
+
from .pipelines import ZeroShotAudioClassificationPipeline as ZeroShotAudioClassificationPipeline
|
| 689 |
+
from .pipelines import ZeroShotClassificationPipeline as ZeroShotClassificationPipeline
|
| 690 |
+
from .pipelines import ZeroShotImageClassificationPipeline as ZeroShotImageClassificationPipeline
|
| 691 |
+
from .pipelines import ZeroShotObjectDetectionPipeline as ZeroShotObjectDetectionPipeline
|
| 692 |
+
from .pipelines import pipeline as pipeline
|
| 693 |
+
from .processing_utils import AudioKwargs as AudioKwargs
|
| 694 |
+
from .processing_utils import ImagesKwargs as ImagesKwargs
|
| 695 |
+
from .processing_utils import ProcessingKwargs as ProcessingKwargs
|
| 696 |
+
from .processing_utils import ProcessorMixin as ProcessorMixin
|
| 697 |
+
from .processing_utils import TextKwargs as TextKwargs
|
| 698 |
+
from .processing_utils import VideosKwargs as VideosKwargs
|
| 699 |
+
from .pytorch_utils import Conv1D as Conv1D
|
| 700 |
+
from .pytorch_utils import apply_chunking_to_forward as apply_chunking_to_forward
|
| 701 |
+
|
| 702 |
+
# Tokenization
|
| 703 |
+
from .tokenization_python import PreTrainedTokenizer as PreTrainedTokenizer
|
| 704 |
+
from .tokenization_python import PythonBackend as PythonBackend
|
| 705 |
+
from .tokenization_utils_base import AddedToken as AddedToken
|
| 706 |
+
from .tokenization_utils_base import BatchEncoding as BatchEncoding
|
| 707 |
+
from .tokenization_utils_base import CharSpan as CharSpan
|
| 708 |
+
from .tokenization_utils_base import PreTrainedTokenizerBase as PreTrainedTokenizerBase
|
| 709 |
+
from .tokenization_utils_base import TokenSpan as TokenSpan
|
| 710 |
+
|
| 711 |
+
# Tokenization
|
| 712 |
+
from .tokenization_utils_sentencepiece import SentencePieceBackend as SentencePieceBackend
|
| 713 |
+
from .tokenization_utils_tokenizers import PreTrainedTokenizerFast as PreTrainedTokenizerFast
|
| 714 |
+
from .tokenization_utils_tokenizers import (
|
| 715 |
+
TokenizersBackend as TokenizersBackend,
|
| 716 |
+
)
|
| 717 |
+
|
| 718 |
+
# Trainer
|
| 719 |
+
from .trainer import Trainer as Trainer
|
| 720 |
+
from .trainer_callback import DefaultFlowCallback as DefaultFlowCallback
|
| 721 |
+
from .trainer_callback import EarlyStoppingCallback as EarlyStoppingCallback
|
| 722 |
+
from .trainer_callback import PrinterCallback as PrinterCallback
|
| 723 |
+
from .trainer_callback import ProgressCallback as ProgressCallback
|
| 724 |
+
from .trainer_callback import TrainerCallback as TrainerCallback
|
| 725 |
+
from .trainer_callback import TrainerControl as TrainerControl
|
| 726 |
+
from .trainer_callback import TrainerState as TrainerState
|
| 727 |
+
from .trainer_pt_utils import torch_distributed_zero_first as torch_distributed_zero_first
|
| 728 |
+
from .trainer_seq2seq import Seq2SeqTrainer as Seq2SeqTrainer
|
| 729 |
+
from .trainer_utils import EvalPrediction as EvalPrediction
|
| 730 |
+
from .trainer_utils import IntervalStrategy as IntervalStrategy
|
| 731 |
+
from .trainer_utils import SchedulerType as SchedulerType
|
| 732 |
+
from .trainer_utils import enable_full_determinism as enable_full_determinism
|
| 733 |
+
from .trainer_utils import set_seed as set_seed
|
| 734 |
+
from .training_args import TrainingArguments as TrainingArguments
|
| 735 |
+
from .training_args_seq2seq import Seq2SeqTrainingArguments as Seq2SeqTrainingArguments
|
| 736 |
+
|
| 737 |
+
# Files and general utilities
|
| 738 |
+
from .utils import CONFIG_NAME as CONFIG_NAME
|
| 739 |
+
from .utils import MODEL_CARD_NAME as MODEL_CARD_NAME
|
| 740 |
+
from .utils import SPIECE_UNDERLINE as SPIECE_UNDERLINE
|
| 741 |
+
from .utils import WEIGHTS_NAME as WEIGHTS_NAME
|
| 742 |
+
from .utils import TensorType as TensorType
|
| 743 |
+
from .utils import add_end_docstrings as add_end_docstrings
|
| 744 |
+
from .utils import add_start_docstrings as add_start_docstrings
|
| 745 |
+
from .utils import is_apex_available as is_apex_available
|
| 746 |
+
from .utils import is_av_available as is_av_available
|
| 747 |
+
from .utils import is_datasets_available as is_datasets_available
|
| 748 |
+
from .utils import is_faiss_available as is_faiss_available
|
| 749 |
+
from .utils import is_matplotlib_available as is_matplotlib_available
|
| 750 |
+
from .utils import is_phonemizer_available as is_phonemizer_available
|
| 751 |
+
from .utils import is_psutil_available as is_psutil_available
|
| 752 |
+
from .utils import is_py3nvml_available as is_py3nvml_available
|
| 753 |
+
from .utils import is_pyctcdecode_available as is_pyctcdecode_available
|
| 754 |
+
from .utils import is_sacremoses_available as is_sacremoses_available
|
| 755 |
+
from .utils import is_sklearn_available as is_sklearn_available
|
| 756 |
+
from .utils import is_torch_hpu_available as is_torch_hpu_available
|
| 757 |
+
from .utils import is_torch_mlu_available as is_torch_mlu_available
|
| 758 |
+
from .utils import is_torch_musa_available as is_torch_musa_available
|
| 759 |
+
from .utils import is_torch_neuroncore_available as is_torch_neuroncore_available
|
| 760 |
+
from .utils import is_torch_npu_available as is_torch_npu_available
|
| 761 |
+
from .utils import is_torch_xla_available as is_torch_xla_available
|
| 762 |
+
from .utils import is_torch_xpu_available as is_torch_xpu_available
|
| 763 |
+
from .utils.import_utils import requires_backends
|
| 764 |
+
from .utils.kernel_config import KernelConfig as KernelConfig
|
| 765 |
+
|
| 766 |
+
# Quantization config
|
| 767 |
+
from .utils.quantization_config import AqlmConfig as AqlmConfig
|
| 768 |
+
from .utils.quantization_config import AutoRoundConfig as AutoRoundConfig
|
| 769 |
+
from .utils.quantization_config import AwqConfig as AwqConfig
|
| 770 |
+
from .utils.quantization_config import BitNetQuantConfig as BitNetQuantConfig
|
| 771 |
+
from .utils.quantization_config import BitsAndBytesConfig as BitsAndBytesConfig
|
| 772 |
+
from .utils.quantization_config import CompressedTensorsConfig as CompressedTensorsConfig
|
| 773 |
+
from .utils.quantization_config import EetqConfig as EetqConfig
|
| 774 |
+
from .utils.quantization_config import FbgemmFp8Config as FbgemmFp8Config
|
| 775 |
+
from .utils.quantization_config import FineGrainedFP8Config as FineGrainedFP8Config
|
| 776 |
+
from .utils.quantization_config import FourOverSixConfig as FourOverSixConfig
|
| 777 |
+
from .utils.quantization_config import FPQuantConfig as FPQuantConfig
|
| 778 |
+
from .utils.quantization_config import GPTQConfig as GPTQConfig
|
| 779 |
+
from .utils.quantization_config import HiggsConfig as HiggsConfig
|
| 780 |
+
from .utils.quantization_config import HqqConfig as HqqConfig
|
| 781 |
+
from .utils.quantization_config import MetalConfig as MetalConfig
|
| 782 |
+
from .utils.quantization_config import QuantoConfig as QuantoConfig
|
| 783 |
+
from .utils.quantization_config import QuarkConfig as QuarkConfig
|
| 784 |
+
from .utils.quantization_config import SinqConfig as SinqConfig
|
| 785 |
+
from .utils.quantization_config import SpQRConfig as SpQRConfig
|
| 786 |
+
from .utils.quantization_config import TorchAoConfig as TorchAoConfig
|
| 787 |
+
from .utils.quantization_config import VptqConfig as VptqConfig
|
| 788 |
+
from .video_processing_utils import BaseVideoProcessor as BaseVideoProcessor
|
| 789 |
+
else:
|
| 790 |
+
_import_structure = {k: set(v) for k, v in _import_structure.items()}
|
| 791 |
+
|
| 792 |
+
import_structure = define_import_structure(Path(__file__).parent / "models", prefix="models")
|
| 793 |
+
import_structure[frozenset({})].update(_import_structure)
|
| 794 |
+
|
| 795 |
+
sys.modules[__name__] = _LazyModule(
|
| 796 |
+
__name__,
|
| 797 |
+
globals()["__file__"],
|
| 798 |
+
import_structure,
|
| 799 |
+
module_spec=__spec__,
|
| 800 |
+
extra_objects={"__version__": __version__},
|
| 801 |
+
)
|
| 802 |
+
|
| 803 |
+
def _create_module_alias(alias: str, target: str) -> None:
|
| 804 |
+
"""
|
| 805 |
+
Lazily redirect legacy module paths to their replacements without importing heavy deps.
|
| 806 |
+
"""
|
| 807 |
+
module = types.ModuleType(alias)
|
| 808 |
+
module.__doc__ = f"Alias module for backward compatibility with `{target}`."
|
| 809 |
+
# Set __file__ explicitly so that inspect.py's hasattr(module, '__file__') check
|
| 810 |
+
# never falls through to __getattr__ and triggers a premature (possibly circular) import.
|
| 811 |
+
module.__file__ = None
|
| 812 |
+
|
| 813 |
+
def _get_target():
|
| 814 |
+
return importlib.import_module(target, __name__)
|
| 815 |
+
|
| 816 |
+
module.__getattr__ = lambda name: getattr(_get_target(), name)
|
| 817 |
+
module.__dir__ = lambda: dir(_get_target())
|
| 818 |
+
|
| 819 |
+
sys.modules[alias] = module
|
| 820 |
+
setattr(sys.modules[__name__], alias.rsplit(".", 1)[-1], module)
|
| 821 |
+
|
| 822 |
+
_create_module_alias(f"{__name__}.tokenization_utils_fast", ".tokenization_utils_tokenizers")
|
| 823 |
+
_create_module_alias(f"{__name__}.tokenization_utils", ".tokenization_utils_sentencepiece")
|
| 824 |
+
_create_module_alias(f"{__name__}.image_processing_utils_fast", ".image_processing_backends")
|
| 825 |
+
|
| 826 |
+
for _proc_file in sorted((Path(__file__).parent / "models").rglob("image_processing_*.py")):
|
| 827 |
+
_model = _proc_file.parent.name
|
| 828 |
+
_module = _proc_file.stem
|
| 829 |
+
_target = f".models.{_model}.{_module}"
|
| 830 |
+
_create_module_alias(f"{__name__}.models.{_model}.{_module}_fast", _target)
|
| 831 |
+
|
| 832 |
+
# Also map XImageProcessorFast -> XImageProcessor for backward compat with old class names.
|
| 833 |
+
def getattr_factory(target):
|
| 834 |
+
def _getattr(name):
|
| 835 |
+
new_name = name.removesuffix("Fast")
|
| 836 |
+
logger.warning(
|
| 837 |
+
"Accessing `%s` from `%s`. Returning `%s` instead. Behavior may be "
|
| 838 |
+
"different and this alias will be removed in future versions.",
|
| 839 |
+
name,
|
| 840 |
+
target,
|
| 841 |
+
new_name,
|
| 842 |
+
)
|
| 843 |
+
return getattr(importlib.import_module(target, __name__), new_name)
|
| 844 |
+
|
| 845 |
+
return _getattr
|
| 846 |
+
|
| 847 |
+
sys.modules[f"{__name__}.models.{_model}.{_module}_fast"].__getattr__ = getattr_factory(_target)
|
| 848 |
+
|
| 849 |
+
if not is_torch_available():
|
| 850 |
+
logger.warning_advice(
|
| 851 |
+
"PyTorch was not found. Models won't be available and only tokenizers, configuration and file/data utilities can be used."
|
| 852 |
+
)
|
third_party/transformers/src/transformers/debug_utils.py
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import collections
|
| 16 |
+
|
| 17 |
+
from .utils import ExplicitEnum, is_torch_available, logging
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if is_torch_available():
|
| 21 |
+
import torch
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
logger = logging.get_logger(__name__)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class DebugUnderflowOverflow:
|
| 28 |
+
"""
|
| 29 |
+
This debug class helps detect and understand where the model starts getting very large or very small, and more
|
| 30 |
+
importantly `nan` or `inf` weight and activation elements.
|
| 31 |
+
|
| 32 |
+
There are 2 working modes:
|
| 33 |
+
|
| 34 |
+
1. Underflow/overflow detection (default)
|
| 35 |
+
2. Specific batch absolute min/max tracing without detection
|
| 36 |
+
|
| 37 |
+
Mode 1: Underflow/overflow detection
|
| 38 |
+
|
| 39 |
+
To activate the underflow/overflow detection, initialize the object with the model :
|
| 40 |
+
|
| 41 |
+
```python
|
| 42 |
+
debug_overflow = DebugUnderflowOverflow(model)
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
then run the training as normal and if `nan` or `inf` gets detected in at least one of the weight, input or output
|
| 46 |
+
elements this module will throw an exception and will print `max_frames_to_save` frames that lead to this event,
|
| 47 |
+
each frame reporting
|
| 48 |
+
|
| 49 |
+
1. the fully qualified module name plus the class name whose `forward` was run
|
| 50 |
+
2. the absolute min and max value of all elements for each module weights, and the inputs and output
|
| 51 |
+
|
| 52 |
+
For example, here is the header and the last few frames in detection report for `google/mt5-small` run in fp16
|
| 53 |
+
mixed precision :
|
| 54 |
+
|
| 55 |
+
```
|
| 56 |
+
Detected inf/nan during batch_number=0
|
| 57 |
+
Last 21 forward frames:
|
| 58 |
+
abs min abs max metadata
|
| 59 |
+
[...]
|
| 60 |
+
encoder.block.2.layer.1.DenseReluDense.wi_0 Linear
|
| 61 |
+
2.17e-07 4.50e+00 weight
|
| 62 |
+
1.79e-06 4.65e+00 input[0]
|
| 63 |
+
2.68e-06 3.70e+01 output
|
| 64 |
+
encoder.block.2.layer.1.DenseReluDense.wi_1 Linear
|
| 65 |
+
8.08e-07 2.66e+01 weight
|
| 66 |
+
1.79e-06 4.65e+00 input[0]
|
| 67 |
+
1.27e-04 2.37e+02 output
|
| 68 |
+
encoder.block.2.layer.1.DenseReluDense.wo Linear
|
| 69 |
+
1.01e-06 6.44e+00 weight
|
| 70 |
+
0.00e+00 9.74e+03 input[0]
|
| 71 |
+
3.18e-04 6.27e+04 output
|
| 72 |
+
encoder.block.2.layer.1.DenseReluDense T5DenseGatedGeluDense
|
| 73 |
+
1.79e-06 4.65e+00 input[0]
|
| 74 |
+
3.18e-04 6.27e+04 output
|
| 75 |
+
encoder.block.2.layer.1.dropout Dropout
|
| 76 |
+
3.18e-04 6.27e+04 input[0]
|
| 77 |
+
0.00e+00 inf output
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
You can see here, that `T5DenseGatedGeluDense.forward` resulted in output activations, whose absolute max value was
|
| 81 |
+
around 62.7K, which is very close to fp16's top limit of 64K. In the next frame we have `Dropout` which
|
| 82 |
+
renormalizes the weights, after it zeroed some of the elements, which pushes the absolute max value to more than
|
| 83 |
+
64K, and we get an overflow.
|
| 84 |
+
|
| 85 |
+
As you can see it's the previous frames that we need to look into when the numbers start going into very large for
|
| 86 |
+
fp16 numbers.
|
| 87 |
+
|
| 88 |
+
The tracking is done in a forward hook, which gets invoked immediately after `forward` has completed.
|
| 89 |
+
|
| 90 |
+
By default the last 21 frames are printed. You can change the default to adjust for your needs. For example :
|
| 91 |
+
|
| 92 |
+
```python
|
| 93 |
+
debug_overflow = DebugUnderflowOverflow(model, max_frames_to_save=100)
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
To validate that you have set up this debugging feature correctly, and you intend to use it in a training that
|
| 97 |
+
may take hours to complete, first run it with normal tracing enabled for one of a few batches as explained in
|
| 98 |
+
the next section.
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
Mode 2. Specific batch absolute min/max tracing without detection
|
| 102 |
+
|
| 103 |
+
The second work mode is per-batch tracing with the underflow/overflow detection feature turned off.
|
| 104 |
+
|
| 105 |
+
Let's say you want to watch the absolute min and max values for all the ingredients of each `forward` call of a
|
| 106 |
+
given batch, and only do that for batches 1 and 3. Then you instantiate this class as :
|
| 107 |
+
|
| 108 |
+
```python
|
| 109 |
+
debug_overflow = DebugUnderflowOverflow(model, trace_batch_nums=[1, 3])
|
| 110 |
+
```
|
| 111 |
+
|
| 112 |
+
And now full batches 1 and 3 will be traced using the same format as explained above. Batches are 0-indexed.
|
| 113 |
+
|
| 114 |
+
This is helpful if you know that the program starts misbehaving after a certain batch number, so you can
|
| 115 |
+
fast-forward right to that area.
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
Early stopping:
|
| 119 |
+
|
| 120 |
+
You can also specify the batch number after which to stop the training, with :
|
| 121 |
+
|
| 122 |
+
```python
|
| 123 |
+
debug_overflow = DebugUnderflowOverflow(model, trace_batch_nums=[1, 3], abort_after_batch_num=3)
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
This feature is mainly useful in the tracing mode, but you can use it for any mode.
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
**Performance**:
|
| 130 |
+
|
| 131 |
+
As this module measures absolute `min`/``max` of each weight of the model on every forward it'll slow the training
|
| 132 |
+
down. Therefore remember to turn it off once the debugging needs have been met.
|
| 133 |
+
|
| 134 |
+
Args:
|
| 135 |
+
model (`nn.Module`):
|
| 136 |
+
The model to debug.
|
| 137 |
+
max_frames_to_save (`int`, *optional*, defaults to 21):
|
| 138 |
+
How many frames back to record
|
| 139 |
+
trace_batch_nums(`list[int]`, *optional*, defaults to `[]`):
|
| 140 |
+
Which batch numbers to trace (turns detection off)
|
| 141 |
+
abort_after_batch_num (`int``, *optional*):
|
| 142 |
+
Whether to abort after a certain batch number has finished
|
| 143 |
+
"""
|
| 144 |
+
|
| 145 |
+
def __init__(self, model, max_frames_to_save=21, trace_batch_nums=None, abort_after_batch_num=None):
|
| 146 |
+
if trace_batch_nums is None:
|
| 147 |
+
trace_batch_nums = []
|
| 148 |
+
self.model = model
|
| 149 |
+
self.trace_batch_nums = trace_batch_nums
|
| 150 |
+
self.abort_after_batch_num = abort_after_batch_num
|
| 151 |
+
|
| 152 |
+
# keep a LIFO buffer of frames to dump as soon as inf/nan is encountered to give context to the problem emergence
|
| 153 |
+
self.frames = collections.deque([], max_frames_to_save)
|
| 154 |
+
self.frame = []
|
| 155 |
+
self.batch_number = 0
|
| 156 |
+
self.total_calls = 0
|
| 157 |
+
self.detected_overflow = False
|
| 158 |
+
self.prefix = " "
|
| 159 |
+
|
| 160 |
+
self.analyse_model()
|
| 161 |
+
|
| 162 |
+
self.register_forward_hook()
|
| 163 |
+
|
| 164 |
+
def save_frame(self, frame=None):
|
| 165 |
+
if frame is not None:
|
| 166 |
+
self.expand_frame(frame)
|
| 167 |
+
self.frames.append("\n".join(self.frame))
|
| 168 |
+
self.frame = [] # start a new frame
|
| 169 |
+
|
| 170 |
+
def expand_frame(self, line):
|
| 171 |
+
self.frame.append(line)
|
| 172 |
+
|
| 173 |
+
def trace_frames(self):
|
| 174 |
+
print("\n".join(self.frames))
|
| 175 |
+
self.frames = []
|
| 176 |
+
|
| 177 |
+
def reset_saved_frames(self):
|
| 178 |
+
self.frames = []
|
| 179 |
+
|
| 180 |
+
def dump_saved_frames(self):
|
| 181 |
+
print(f"\nDetected inf/nan during batch_number={self.batch_number}")
|
| 182 |
+
print(f"Last {len(self.frames)} forward frames:")
|
| 183 |
+
print(f"{'abs min':8} {'abs max':8} metadata")
|
| 184 |
+
print("\n".join(self.frames))
|
| 185 |
+
print("\n\n")
|
| 186 |
+
self.frames = []
|
| 187 |
+
|
| 188 |
+
def analyse_model(self):
|
| 189 |
+
# extract the fully qualified module names, to be able to report at run time. e.g.:
|
| 190 |
+
# encoder.block.2.layer.0.SelfAttention.o
|
| 191 |
+
#
|
| 192 |
+
# for shared weights only the first shared module name will be registered
|
| 193 |
+
self.module_names = {m: name for name, m in self.model.named_modules()}
|
| 194 |
+
# self.longest_module_name = max(len(v) for v in self.module_names.values())
|
| 195 |
+
|
| 196 |
+
def analyse_variable(self, var, ctx):
|
| 197 |
+
if torch.is_tensor(var):
|
| 198 |
+
self.expand_frame(get_abs_min_max(var, ctx))
|
| 199 |
+
if detect_overflow(var, ctx):
|
| 200 |
+
self.detected_overflow = True
|
| 201 |
+
elif var is None:
|
| 202 |
+
self.expand_frame(f"{'None':>17} {ctx}")
|
| 203 |
+
else:
|
| 204 |
+
self.expand_frame(f"{'not a tensor':>17} {ctx}")
|
| 205 |
+
|
| 206 |
+
def batch_start_frame(self):
|
| 207 |
+
self.expand_frame(f"\n\n{self.prefix} *** Starting batch number={self.batch_number} ***")
|
| 208 |
+
self.expand_frame(f"{'abs min':8} {'abs max':8} metadata")
|
| 209 |
+
|
| 210 |
+
def batch_end_frame(self):
|
| 211 |
+
self.expand_frame(f"{self.prefix} *** Finished batch number={self.batch_number - 1} ***\n\n")
|
| 212 |
+
|
| 213 |
+
def create_frame(self, module, input, output):
|
| 214 |
+
self.expand_frame(f"{self.prefix} {self.module_names[module]} {module.__class__.__name__}")
|
| 215 |
+
|
| 216 |
+
# params
|
| 217 |
+
for name, p in module.named_parameters(recurse=False):
|
| 218 |
+
self.analyse_variable(p, name)
|
| 219 |
+
|
| 220 |
+
# inputs
|
| 221 |
+
if isinstance(input, tuple):
|
| 222 |
+
for i, x in enumerate(input):
|
| 223 |
+
self.analyse_variable(x, f"input[{i}]")
|
| 224 |
+
else:
|
| 225 |
+
self.analyse_variable(input, "input")
|
| 226 |
+
|
| 227 |
+
# outputs
|
| 228 |
+
if isinstance(output, tuple):
|
| 229 |
+
for i, x in enumerate(output):
|
| 230 |
+
# possibly a tuple of tuples
|
| 231 |
+
if isinstance(x, tuple):
|
| 232 |
+
for j, y in enumerate(x):
|
| 233 |
+
self.analyse_variable(y, f"output[{i}][{j}]")
|
| 234 |
+
else:
|
| 235 |
+
self.analyse_variable(x, f"output[{i}]")
|
| 236 |
+
else:
|
| 237 |
+
self.analyse_variable(output, "output")
|
| 238 |
+
|
| 239 |
+
self.save_frame()
|
| 240 |
+
|
| 241 |
+
def register_forward_hook(self):
|
| 242 |
+
self.model.apply(self._register_forward_hook)
|
| 243 |
+
|
| 244 |
+
def _register_forward_hook(self, module):
|
| 245 |
+
module.register_forward_hook(self.forward_hook)
|
| 246 |
+
|
| 247 |
+
def forward_hook(self, module, input, output):
|
| 248 |
+
# - input is a tuple of packed inputs (could be non-Tensors)
|
| 249 |
+
# - output could be a Tensor or a tuple of Tensors and non-Tensors
|
| 250 |
+
|
| 251 |
+
last_frame_of_batch = False
|
| 252 |
+
|
| 253 |
+
trace_mode = self.batch_number in self.trace_batch_nums
|
| 254 |
+
if trace_mode:
|
| 255 |
+
self.reset_saved_frames()
|
| 256 |
+
|
| 257 |
+
if self.total_calls == 0:
|
| 258 |
+
self.batch_start_frame()
|
| 259 |
+
self.total_calls += 1
|
| 260 |
+
|
| 261 |
+
# count batch numbers - the very first forward hook of the batch will be called when the
|
| 262 |
+
# batch completes - i.e. it gets called very last - we know this batch has finished
|
| 263 |
+
if module == self.model:
|
| 264 |
+
self.batch_number += 1
|
| 265 |
+
last_frame_of_batch = True
|
| 266 |
+
|
| 267 |
+
self.create_frame(module, input, output)
|
| 268 |
+
|
| 269 |
+
# if last_frame_of_batch:
|
| 270 |
+
# self.batch_end_frame()
|
| 271 |
+
|
| 272 |
+
if trace_mode:
|
| 273 |
+
self.trace_frames()
|
| 274 |
+
|
| 275 |
+
if last_frame_of_batch:
|
| 276 |
+
self.batch_start_frame()
|
| 277 |
+
|
| 278 |
+
if self.detected_overflow and not trace_mode:
|
| 279 |
+
self.dump_saved_frames()
|
| 280 |
+
|
| 281 |
+
# now we can abort, as it's pointless to continue running
|
| 282 |
+
raise ValueError(
|
| 283 |
+
"DebugUnderflowOverflow: inf/nan detected, aborting as there is no point running further. "
|
| 284 |
+
"Please scroll up above this traceback to see the activation values prior to this event."
|
| 285 |
+
)
|
| 286 |
+
|
| 287 |
+
# abort after certain batch if requested to do so
|
| 288 |
+
if self.abort_after_batch_num is not None and self.batch_number > self.abort_after_batch_num:
|
| 289 |
+
raise ValueError(
|
| 290 |
+
f"DebugUnderflowOverflow: aborting after {self.batch_number} batches due to"
|
| 291 |
+
f" `abort_after_batch_num={self.abort_after_batch_num}` arg"
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
def get_abs_min_max(var, ctx):
|
| 296 |
+
abs_var = var.abs()
|
| 297 |
+
return f"{abs_var.min():8.2e} {abs_var.max():8.2e} {ctx}"
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
def detect_overflow(var, ctx):
|
| 301 |
+
"""
|
| 302 |
+
Report whether the tensor contains any `nan` or `inf` entries.
|
| 303 |
+
|
| 304 |
+
This is useful for detecting overflows/underflows and best to call right after the function that did some math that
|
| 305 |
+
modified the tensor in question.
|
| 306 |
+
|
| 307 |
+
This function contains a few other helper features that you can enable and tweak directly if you want to track
|
| 308 |
+
various other things.
|
| 309 |
+
|
| 310 |
+
Args:
|
| 311 |
+
var: the tensor variable to check
|
| 312 |
+
ctx: the message to print as a context
|
| 313 |
+
|
| 314 |
+
Return:
|
| 315 |
+
`True` if `inf` or `nan` was detected, `False` otherwise
|
| 316 |
+
"""
|
| 317 |
+
detected = False
|
| 318 |
+
if torch.isnan(var).any().item():
|
| 319 |
+
detected = True
|
| 320 |
+
print(f"{ctx} has nans")
|
| 321 |
+
if torch.isinf(var).any().item():
|
| 322 |
+
detected = True
|
| 323 |
+
print(f"{ctx} has infs")
|
| 324 |
+
|
| 325 |
+
# if needed to monitor large elements can enable the following
|
| 326 |
+
if 0: # and detected:
|
| 327 |
+
n100 = var[torch.ge(var.abs(), 100)]
|
| 328 |
+
if n100.numel() > 0:
|
| 329 |
+
print(f"{ctx}: n100={n100.numel()}")
|
| 330 |
+
n1000 = var[torch.ge(var.abs(), 1000)]
|
| 331 |
+
if n1000.numel() > 0:
|
| 332 |
+
print(f"{ctx}: n1000={n1000.numel()}")
|
| 333 |
+
n10000 = var[torch.ge(var.abs(), 10000)]
|
| 334 |
+
if n10000.numel() > 0:
|
| 335 |
+
print(f"{ctx}: n10000={n10000.numel()}")
|
| 336 |
+
|
| 337 |
+
if 0:
|
| 338 |
+
print(f"min={var.min():9.2e} max={var.max():9.2e}")
|
| 339 |
+
|
| 340 |
+
if 0:
|
| 341 |
+
print(f"min={var.min():9.2e} max={var.max():9.2e} var={var.var():9.2e} mean={var.mean():9.2e} ({ctx})")
|
| 342 |
+
|
| 343 |
+
return detected
|
| 344 |
+
|
| 345 |
+
|
| 346 |
+
class DebugOption(ExplicitEnum):
|
| 347 |
+
UNDERFLOW_OVERFLOW = "underflow_overflow"
|
| 348 |
+
TPU_METRICS_DEBUG = "tpu_metrics_debug"
|
third_party/transformers/src/transformers/distributed/__init__.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from typing import TYPE_CHECKING
|
| 16 |
+
|
| 17 |
+
from ..utils import _LazyModule
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
_import_structure = {
|
| 21 |
+
"configuration_utils": ["DistributedConfig"],
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
if TYPE_CHECKING:
|
| 26 |
+
from .configuration_utils import (
|
| 27 |
+
DistributedConfig,
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
else:
|
| 31 |
+
import sys
|
| 32 |
+
|
| 33 |
+
sys.modules[__name__] = _LazyModule(__name__, globals()["__file__"], _import_structure, module_spec=__spec__)
|
third_party/transformers/src/transformers/distributed/configuration_utils.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import copy
|
| 16 |
+
import json
|
| 17 |
+
import os
|
| 18 |
+
from dataclasses import dataclass
|
| 19 |
+
from typing import Any
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@dataclass
|
| 23 |
+
class DistributedConfig:
|
| 24 |
+
"""
|
| 25 |
+
Base class for distributed configs
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
enable_expert_parallel: bool = False
|
| 29 |
+
# TODO: add tp_plan, pp_plan, device_mesh etc..
|
| 30 |
+
|
| 31 |
+
@classmethod
|
| 32 |
+
def from_dict(cls, config_dict, **kwargs):
|
| 33 |
+
"""
|
| 34 |
+
Constructs a DistributedConfig instance from a dictionary of parameters.
|
| 35 |
+
Args:
|
| 36 |
+
config_dict (Dict[str, Any]): Dictionary containing configuration parameters.
|
| 37 |
+
**kwargs: Additional keyword arguments to override dictionary values.
|
| 38 |
+
Returns:
|
| 39 |
+
DistributedConfig: Instance of DistributedConfig constructed from the dictionary.
|
| 40 |
+
"""
|
| 41 |
+
config = cls(**config_dict)
|
| 42 |
+
to_remove = []
|
| 43 |
+
for key, value in kwargs.items():
|
| 44 |
+
if hasattr(config, key):
|
| 45 |
+
setattr(config, key, value)
|
| 46 |
+
to_remove.append(key)
|
| 47 |
+
for key in to_remove:
|
| 48 |
+
kwargs.pop(key, None)
|
| 49 |
+
return config
|
| 50 |
+
|
| 51 |
+
# Copied from transformers.utils.quantization_config.QuantizationConfigMixin.to_json_file
|
| 52 |
+
def to_json_file(self, json_file_path: str | os.PathLike):
|
| 53 |
+
"""
|
| 54 |
+
Save this instance to a JSON file.
|
| 55 |
+
Args:
|
| 56 |
+
json_file_path (`str` or `os.PathLike`):
|
| 57 |
+
Path to the JSON file in which this configuration instance's parameters will be saved.
|
| 58 |
+
use_diff (`bool`, *optional*, defaults to `True`):
|
| 59 |
+
If set to `True`, only the difference between the config instance and the default
|
| 60 |
+
`QuantizationConfig()` is serialized to JSON file.
|
| 61 |
+
"""
|
| 62 |
+
with open(json_file_path, "w", encoding="utf-8") as writer:
|
| 63 |
+
config_dict = self.to_dict()
|
| 64 |
+
json_string = json.dumps(config_dict, indent=2, sort_keys=True) + "\n"
|
| 65 |
+
|
| 66 |
+
writer.write(json_string)
|
| 67 |
+
|
| 68 |
+
def to_dict(self) -> dict[str, Any]:
|
| 69 |
+
"""
|
| 70 |
+
Serializes this instance to a Python dictionary. Returns:
|
| 71 |
+
`Dict[str, Any]`: Dictionary of all the attributes that make up this configuration instance.
|
| 72 |
+
"""
|
| 73 |
+
return copy.deepcopy(self.__dict__)
|
| 74 |
+
|
| 75 |
+
# Copied from transformers.utils.quantization_config.QuantizationConfigMixin.__iter__
|
| 76 |
+
def __iter__(self):
|
| 77 |
+
"""allows `dict(obj)` for situations where obj may be a dict or QuantizationConfigMixin"""
|
| 78 |
+
yield from copy.deepcopy(self.__dict__).items()
|
| 79 |
+
|
| 80 |
+
# Copied from transformers.utils.quantization_config.QuantizationConfigMixin.__repr__
|
| 81 |
+
def __repr__(self):
|
| 82 |
+
return f"{self.__class__.__name__} {self.to_json_string()}"
|
| 83 |
+
|
| 84 |
+
def to_json_string(self):
|
| 85 |
+
"""
|
| 86 |
+
Serializes this instance to a JSON formatted string.
|
| 87 |
+
Returns:
|
| 88 |
+
str: JSON formatted string representing the configuration instance.
|
| 89 |
+
"""
|
| 90 |
+
return json.dumps(self.__dict__, indent=2) + "\n"
|
| 91 |
+
|
| 92 |
+
def update(self, **kwargs):
|
| 93 |
+
"""
|
| 94 |
+
Updates attributes of this class instance with attributes from `kwargs` if they match existing attributes,
|
| 95 |
+
returning all the unused kwargs.
|
| 96 |
+
Args:
|
| 97 |
+
kwargs (`Dict[str, Any]`):
|
| 98 |
+
Dictionary of attributes to tentatively update this class.
|
| 99 |
+
Returns:
|
| 100 |
+
`Dict[str, Any]`: Dictionary containing all the key-value pairs that were not used to update the instance.
|
| 101 |
+
"""
|
| 102 |
+
to_remove = []
|
| 103 |
+
for key, value in kwargs.items():
|
| 104 |
+
if hasattr(self, key):
|
| 105 |
+
setattr(self, key, value)
|
| 106 |
+
to_remove.append(key)
|
| 107 |
+
|
| 108 |
+
# Remove all the attributes that were updated, without modifying the input dict
|
| 109 |
+
unused_kwargs = {key: value for key, value in kwargs.items() if key not in to_remove}
|
| 110 |
+
return unused_kwargs
|
third_party/transformers/src/transformers/hyperparameter_search.py
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023-present the HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from .integrations import (
|
| 16 |
+
is_optuna_available,
|
| 17 |
+
is_ray_tune_available,
|
| 18 |
+
is_wandb_available,
|
| 19 |
+
run_hp_search_optuna,
|
| 20 |
+
run_hp_search_ray,
|
| 21 |
+
run_hp_search_wandb,
|
| 22 |
+
)
|
| 23 |
+
from .trainer_utils import (
|
| 24 |
+
HPSearchBackend,
|
| 25 |
+
default_hp_space_optuna,
|
| 26 |
+
default_hp_space_ray,
|
| 27 |
+
default_hp_space_wandb,
|
| 28 |
+
)
|
| 29 |
+
from .utils import logging
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
logger = logging.get_logger(__name__)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class HyperParamSearchBackendBase:
|
| 36 |
+
name: str
|
| 37 |
+
pip_package: str | None = None
|
| 38 |
+
|
| 39 |
+
@staticmethod
|
| 40 |
+
def is_available():
|
| 41 |
+
raise NotImplementedError
|
| 42 |
+
|
| 43 |
+
def run(self, trainer, n_trials: int, direction: str, **kwargs):
|
| 44 |
+
raise NotImplementedError
|
| 45 |
+
|
| 46 |
+
def default_hp_space(self, trial):
|
| 47 |
+
raise NotImplementedError
|
| 48 |
+
|
| 49 |
+
def ensure_available(self):
|
| 50 |
+
if not self.is_available():
|
| 51 |
+
raise RuntimeError(
|
| 52 |
+
f"You picked the {self.name} backend, but it is not installed. Run {self.pip_install()}."
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
@classmethod
|
| 56 |
+
def pip_install(cls):
|
| 57 |
+
return f"`pip install {cls.pip_package or cls.name}`"
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class OptunaBackend(HyperParamSearchBackendBase):
|
| 61 |
+
name = "optuna"
|
| 62 |
+
|
| 63 |
+
@staticmethod
|
| 64 |
+
def is_available():
|
| 65 |
+
return is_optuna_available()
|
| 66 |
+
|
| 67 |
+
def run(self, trainer, n_trials: int, direction: str, **kwargs):
|
| 68 |
+
return run_hp_search_optuna(trainer, n_trials, direction, **kwargs)
|
| 69 |
+
|
| 70 |
+
def default_hp_space(self, trial):
|
| 71 |
+
return default_hp_space_optuna(trial)
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
class RayTuneBackend(HyperParamSearchBackendBase):
|
| 75 |
+
name = "ray"
|
| 76 |
+
pip_package = "'ray[tune]'"
|
| 77 |
+
|
| 78 |
+
@staticmethod
|
| 79 |
+
def is_available():
|
| 80 |
+
return is_ray_tune_available()
|
| 81 |
+
|
| 82 |
+
def run(self, trainer, n_trials: int, direction: str, **kwargs):
|
| 83 |
+
return run_hp_search_ray(trainer, n_trials, direction, **kwargs)
|
| 84 |
+
|
| 85 |
+
def default_hp_space(self, trial):
|
| 86 |
+
return default_hp_space_ray(trial)
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
class WandbBackend(HyperParamSearchBackendBase):
|
| 90 |
+
name = "wandb"
|
| 91 |
+
|
| 92 |
+
@staticmethod
|
| 93 |
+
def is_available():
|
| 94 |
+
return is_wandb_available()
|
| 95 |
+
|
| 96 |
+
def run(self, trainer, n_trials: int, direction: str, **kwargs):
|
| 97 |
+
return run_hp_search_wandb(trainer, n_trials, direction, **kwargs)
|
| 98 |
+
|
| 99 |
+
def default_hp_space(self, trial):
|
| 100 |
+
return default_hp_space_wandb(trial)
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
ALL_HYPERPARAMETER_SEARCH_BACKENDS = {
|
| 104 |
+
HPSearchBackend(backend.name): backend for backend in [OptunaBackend, RayTuneBackend, WandbBackend]
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def default_hp_search_backend() -> str:
|
| 109 |
+
available_backends = [backend for backend in ALL_HYPERPARAMETER_SEARCH_BACKENDS.values() if backend.is_available()]
|
| 110 |
+
if len(available_backends) > 0:
|
| 111 |
+
name = available_backends[0].name
|
| 112 |
+
if len(available_backends) > 1:
|
| 113 |
+
logger.info(
|
| 114 |
+
f"{len(available_backends)} hyperparameter search backends available. Using {name} as the default."
|
| 115 |
+
)
|
| 116 |
+
return name
|
| 117 |
+
raise RuntimeError(
|
| 118 |
+
"No hyperparameter search backend available.\n"
|
| 119 |
+
+ "\n".join(
|
| 120 |
+
f" - To install {backend.name} run {backend.pip_install()}"
|
| 121 |
+
for backend in ALL_HYPERPARAMETER_SEARCH_BACKENDS.values()
|
| 122 |
+
)
|
| 123 |
+
)
|
third_party/transformers/src/transformers/masking_utils.py
ADDED
|
@@ -0,0 +1,1608 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
import itertools
|
| 15 |
+
from collections.abc import Callable
|
| 16 |
+
|
| 17 |
+
import torch
|
| 18 |
+
import torch.nn.functional as F
|
| 19 |
+
|
| 20 |
+
from .cache_utils import Cache
|
| 21 |
+
from .configuration_utils import PreTrainedConfig
|
| 22 |
+
from .utils import is_torch_xpu_available, logging
|
| 23 |
+
from .utils.deprecation import deprecate_kwarg
|
| 24 |
+
from .utils.generic import GeneralInterface, is_flash_attention_requested
|
| 25 |
+
from .utils.import_utils import is_torch_flex_attn_available, is_torch_greater_or_equal, is_tracing
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
if is_torch_flex_attn_available():
|
| 29 |
+
from torch.nn.attention.flex_attention import _DEFAULT_SPARSE_BLOCK_SIZE as flex_default_block_size
|
| 30 |
+
from torch.nn.attention.flex_attention import BlockMask, create_block_mask
|
| 31 |
+
else:
|
| 32 |
+
# Register a fake type to avoid crashing for annotations and `isinstance` checks
|
| 33 |
+
BlockMask = torch.Tensor
|
| 34 |
+
|
| 35 |
+
_is_torch_greater_or_equal_than_2_5 = is_torch_greater_or_equal("2.5", accept_dev=True)
|
| 36 |
+
_is_torch_greater_or_equal_than_2_6 = is_torch_greater_or_equal("2.6", accept_dev=True)
|
| 37 |
+
_is_torch_xpu_available = is_torch_xpu_available()
|
| 38 |
+
|
| 39 |
+
if _is_torch_greater_or_equal_than_2_6:
|
| 40 |
+
from torch._dynamo._trace_wrapped_higher_order_op import TransformGetItemToIndex
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
logger = logging.get_logger(__name__)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def and_masks(*mask_functions: Callable) -> Callable:
|
| 47 |
+
"""Returns a mask function that is the intersection of provided mask functions"""
|
| 48 |
+
if not all(callable(arg) for arg in mask_functions):
|
| 49 |
+
raise RuntimeError(f"All inputs should be callable mask_functions: {mask_functions}")
|
| 50 |
+
|
| 51 |
+
def and_mask(batch_idx, head_idx, q_idx, kv_idx):
|
| 52 |
+
result = q_idx.new_ones((), dtype=torch.bool)
|
| 53 |
+
for mask in mask_functions:
|
| 54 |
+
result = result & mask(batch_idx, head_idx, q_idx, kv_idx).to(result.device)
|
| 55 |
+
return result
|
| 56 |
+
|
| 57 |
+
return and_mask
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def or_masks(*mask_functions: Callable) -> Callable:
|
| 61 |
+
"""Returns a mask function that is the union of provided mask functions"""
|
| 62 |
+
if not all(callable(arg) for arg in mask_functions):
|
| 63 |
+
raise RuntimeError(f"All inputs should be callable mask_functions: {mask_functions}")
|
| 64 |
+
|
| 65 |
+
def or_mask(batch_idx, head_idx, q_idx, kv_idx):
|
| 66 |
+
result = q_idx.new_zeros((), dtype=torch.bool)
|
| 67 |
+
for mask in mask_functions:
|
| 68 |
+
result = result | mask(batch_idx, head_idx, q_idx, kv_idx).to(result.device)
|
| 69 |
+
return result
|
| 70 |
+
|
| 71 |
+
return or_mask
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def causal_mask_function(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
|
| 75 |
+
"""
|
| 76 |
+
This creates a basic lower-diagonal causal mask.
|
| 77 |
+
"""
|
| 78 |
+
return kv_idx <= q_idx
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def bidirectional_mask_function(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
|
| 82 |
+
"""
|
| 83 |
+
This creates a full bidirectional mask.
|
| 84 |
+
|
| 85 |
+
NOTE: It is important to keep an index-based version for non-vmap expansion.
|
| 86 |
+
"""
|
| 87 |
+
return q_idx >= 0
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def sliding_window_overlay(sliding_window: int) -> Callable:
|
| 91 |
+
"""
|
| 92 |
+
This is an overlay depicting a sliding window pattern. Add it on top of a causal mask for a proper sliding
|
| 93 |
+
window mask.
|
| 94 |
+
"""
|
| 95 |
+
|
| 96 |
+
def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
|
| 97 |
+
return kv_idx > q_idx - sliding_window
|
| 98 |
+
|
| 99 |
+
return inner_mask
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def chunked_overlay(chunk_size: int, left_padding: torch.Tensor) -> Callable:
|
| 103 |
+
"""
|
| 104 |
+
This is an overlay depicting a chunked attention pattern. Add it on top of a causal mask for a proper chunked
|
| 105 |
+
attention mask.
|
| 106 |
+
"""
|
| 107 |
+
|
| 108 |
+
def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
|
| 109 |
+
return (kv_idx - left_padding[batch_idx]) // chunk_size == (q_idx - left_padding[batch_idx]) // chunk_size
|
| 110 |
+
|
| 111 |
+
return inner_mask
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
def sliding_window_causal_mask_function(sliding_window: int) -> Callable:
|
| 115 |
+
"""
|
| 116 |
+
This return the mask_function function to create a sliding window mask.
|
| 117 |
+
"""
|
| 118 |
+
return and_masks(sliding_window_overlay(sliding_window), causal_mask_function)
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def sliding_window_bidirectional_overlay(sliding_window: int) -> Callable:
|
| 122 |
+
"""
|
| 123 |
+
This is an overlay depicting a bidirectional sliding window pattern.
|
| 124 |
+
"""
|
| 125 |
+
|
| 126 |
+
def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
|
| 127 |
+
"""A token can attend to any other token if their absolute distance is within
|
| 128 |
+
the (inclusive) sliding window size (distance <= sliding_window)."""
|
| 129 |
+
return abs(q_idx - kv_idx) <= sliding_window
|
| 130 |
+
|
| 131 |
+
return inner_mask
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def sliding_window_bidirectional_mask_function(sliding_window: int) -> Callable:
|
| 135 |
+
"""
|
| 136 |
+
This return the mask_function function to create a bidirectional sliding window mask.
|
| 137 |
+
"""
|
| 138 |
+
return and_masks(sliding_window_bidirectional_overlay(sliding_window), bidirectional_mask_function)
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def chunked_causal_mask_function(chunk_size: int, left_padding: torch.Tensor) -> Callable:
|
| 142 |
+
"""
|
| 143 |
+
This return the mask_function function to create a chunked attention mask.
|
| 144 |
+
"""
|
| 145 |
+
return and_masks(chunked_overlay(chunk_size, left_padding), causal_mask_function)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def padding_mask_function(padding_mask: torch.Tensor) -> Callable:
|
| 149 |
+
"""
|
| 150 |
+
This return the mask_function function corresponding to a 2D padding mask.
|
| 151 |
+
"""
|
| 152 |
+
|
| 153 |
+
def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
|
| 154 |
+
# Note that here the mask should ALWAYS be at least of the max `kv_index` size in the dimension 1. This is because
|
| 155 |
+
# we cannot pad it here in the mask_function as we don't know the final size, and we cannot try/except, as it is not
|
| 156 |
+
# vectorizable on accelerator devices
|
| 157 |
+
return padding_mask[batch_idx, kv_idx]
|
| 158 |
+
|
| 159 |
+
return inner_mask
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
def packed_sequence_mask_function(packed_sequence_mask: torch.Tensor) -> Callable:
|
| 163 |
+
"""
|
| 164 |
+
This return the mask_function function corresponding to a 2D packed sequence mask.
|
| 165 |
+
"""
|
| 166 |
+
|
| 167 |
+
def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
|
| 168 |
+
return packed_sequence_mask[batch_idx, q_idx] == packed_sequence_mask[batch_idx, kv_idx]
|
| 169 |
+
|
| 170 |
+
return inner_mask
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
def add_offsets_to_mask_function(mask_function: Callable, q_offset: int, kv_offset: int) -> Callable:
|
| 174 |
+
"""
|
| 175 |
+
This function adds the correct offsets to the `q_idx` and `kv_idx` as the torch API can only accept lengths,
|
| 176 |
+
not start and end indices.
|
| 177 |
+
"""
|
| 178 |
+
|
| 179 |
+
def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
|
| 180 |
+
return mask_function(batch_idx, head_idx, q_idx + q_offset, kv_idx + kv_offset)
|
| 181 |
+
|
| 182 |
+
return inner_mask
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
def prepare_padding_mask(attention_mask: torch.Tensor | None, kv_length: int, kv_offset: int) -> torch.Tensor | None:
|
| 186 |
+
"""
|
| 187 |
+
From the 2D attention mask, prepare the correct padding mask to use by potentially padding it.
|
| 188 |
+
"""
|
| 189 |
+
local_padding_mask = attention_mask
|
| 190 |
+
if attention_mask is not None:
|
| 191 |
+
# Pad it if necessary
|
| 192 |
+
if (padding_length := kv_length + kv_offset - attention_mask.shape[-1]) > 0:
|
| 193 |
+
local_padding_mask = torch.nn.functional.pad(attention_mask, (0, padding_length))
|
| 194 |
+
return local_padding_mask
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
def _can_skip_causal_mask_xpu(
|
| 198 |
+
padding_mask: torch.Tensor | None,
|
| 199 |
+
query_length: int,
|
| 200 |
+
kv_length: int,
|
| 201 |
+
local_attention_size: int | None,
|
| 202 |
+
) -> bool:
|
| 203 |
+
"""
|
| 204 |
+
XPU-specific logic for determining if we can skip causal mask creation.
|
| 205 |
+
|
| 206 |
+
For XPU devices, we have special handling:
|
| 207 |
+
- Single query tokens (query_length == 1) use the same logic as CUDA
|
| 208 |
+
- Multi-query tokens can skip if padding_mask is provided and correctly structured
|
| 209 |
+
The mask must have all True values in the query window and all False after
|
| 210 |
+
"""
|
| 211 |
+
|
| 212 |
+
if is_tracing(padding_mask):
|
| 213 |
+
return False
|
| 214 |
+
|
| 215 |
+
# Check local attention constraint (same as CUDA)
|
| 216 |
+
if local_attention_size is not None and kv_length >= local_attention_size:
|
| 217 |
+
return False
|
| 218 |
+
|
| 219 |
+
if padding_mask is None:
|
| 220 |
+
# Without padding mask, can skip if single query token or full causal attention
|
| 221 |
+
return query_length == 1 or kv_length == query_length
|
| 222 |
+
|
| 223 |
+
# XPU allows skipping under additional conditions when padding_mask is provided
|
| 224 |
+
if query_length == 1:
|
| 225 |
+
# Single query token: skip only if no padding tokens present
|
| 226 |
+
return padding_mask.all()
|
| 227 |
+
|
| 228 |
+
# XPU-specific: check if query window is all True and rest is all False
|
| 229 |
+
# This allows XPU to optimize the 1st token in static cache
|
| 230 |
+
return padding_mask[:, :query_length].all() and not padding_mask[:, query_length:].any()
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def _ignore_causal_mask_sdpa(
|
| 234 |
+
padding_mask: torch.Tensor | None,
|
| 235 |
+
query_length: int,
|
| 236 |
+
kv_length: int,
|
| 237 |
+
kv_offset: int,
|
| 238 |
+
local_attention_size: int | None = None,
|
| 239 |
+
) -> bool:
|
| 240 |
+
"""
|
| 241 |
+
Detects whether the causal mask can be ignored in case PyTorch's SDPA is used, rather relying on SDPA's `is_causal` argument.
|
| 242 |
+
|
| 243 |
+
In case no token is masked in the 2D `padding_mask` argument, if `query_length == 1` or
|
| 244 |
+
`key_value_length == query_length`, we rather rely on SDPA `is_causal` argument to use causal/non-causal masks,
|
| 245 |
+
allowing to dispatch to the flash attention kernel (that can otherwise not be used if a custom `attn_mask` is
|
| 246 |
+
passed).
|
| 247 |
+
"""
|
| 248 |
+
if padding_mask is not None and padding_mask.shape[-1] > kv_length:
|
| 249 |
+
mask_indices = torch.arange(kv_length, device=padding_mask.device)
|
| 250 |
+
mask_indices += kv_offset
|
| 251 |
+
padding_mask = padding_mask[:, mask_indices]
|
| 252 |
+
|
| 253 |
+
if _is_torch_xpu_available:
|
| 254 |
+
# XPU devices have special handling for mask skipping:
|
| 255 |
+
# - Single query tokens use the same logic as CUDA
|
| 256 |
+
# - Multi-query tokens can skip if padding_mask is provided and correctly structured
|
| 257 |
+
# (all True in query window, all False after)
|
| 258 |
+
return _can_skip_causal_mask_xpu(padding_mask, query_length, kv_length, local_attention_size)
|
| 259 |
+
# When using `torch.export` or `torch.onnx.dynamo_export`, we must pass an example input, and `is_causal` behavior is
|
| 260 |
+
# hard-coded to the forward. If a user exports a model with query_length > 1, the exported model will hard-code `is_causal=True`
|
| 261 |
+
# which is in general wrong (see https://github.com/pytorch/pytorch/issues/108108). Thus, we only set
|
| 262 |
+
# `ignore_causal_mask = True` if we are not tracing
|
| 263 |
+
if (
|
| 264 |
+
not is_tracing(padding_mask)
|
| 265 |
+
# only cases when lower and upper diags are the same, see https://github.com/pytorch/pytorch/issues/108108
|
| 266 |
+
and (query_length == 1 or kv_length == query_length)
|
| 267 |
+
# in this case we need to add special patterns to the mask so cannot be skipped otherwise
|
| 268 |
+
and (local_attention_size is None or kv_length < local_attention_size)
|
| 269 |
+
# In this case, we need to add padding to the mask, so cannot be skipped otherwise
|
| 270 |
+
and (padding_mask is None or padding_mask.all())
|
| 271 |
+
):
|
| 272 |
+
return True
|
| 273 |
+
|
| 274 |
+
return False
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
def _can_skip_bidirectional_mask_xpu(
|
| 278 |
+
padding_mask: torch.Tensor | None,
|
| 279 |
+
kv_length: int,
|
| 280 |
+
local_attention_size: int | None,
|
| 281 |
+
) -> bool:
|
| 282 |
+
"""
|
| 283 |
+
XPU-specific logic for determining if we can skip bidirectional mask creation.
|
| 284 |
+
|
| 285 |
+
For XPU devices, we have special handling:
|
| 286 |
+
- Skip if no padding and no local attention constraint
|
| 287 |
+
"""
|
| 288 |
+
|
| 289 |
+
if is_tracing(padding_mask):
|
| 290 |
+
return False
|
| 291 |
+
|
| 292 |
+
# Check local attention constraint (same as CUDA)
|
| 293 |
+
if local_attention_size is not None and kv_length >= local_attention_size:
|
| 294 |
+
return False
|
| 295 |
+
|
| 296 |
+
if padding_mask is None:
|
| 297 |
+
# Without padding mask, can always skip for full bidirectional attention
|
| 298 |
+
return True
|
| 299 |
+
|
| 300 |
+
# Skip only if no padding tokens present
|
| 301 |
+
return padding_mask.all()
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
def _ignore_bidirectional_mask_sdpa(
|
| 305 |
+
padding_mask: torch.Tensor | None,
|
| 306 |
+
kv_length: int,
|
| 307 |
+
local_attention_size: int | None = None,
|
| 308 |
+
) -> bool:
|
| 309 |
+
"""
|
| 310 |
+
Detects whether the bidirectional mask can be ignored in case PyTorch's SDPA is used.
|
| 311 |
+
|
| 312 |
+
In case no token is masked in the 2D `padding_mask` argument and no local attention constraint applies
|
| 313 |
+
(i.e. `local_attention_size` is None or `kv_length < local_attention_size`), we skip mask creation,
|
| 314 |
+
allowing to dispatch to the flash attention kernel (that can otherwise not be used if a custom `attn_mask` is
|
| 315 |
+
passed).
|
| 316 |
+
"""
|
| 317 |
+
if _is_torch_xpu_available:
|
| 318 |
+
# XPU devices have special handling for mask skipping:
|
| 319 |
+
# - Skip if no padding and no local attention constraint
|
| 320 |
+
return _can_skip_bidirectional_mask_xpu(padding_mask, kv_length, local_attention_size)
|
| 321 |
+
|
| 322 |
+
# When using `torch.export` or `torch.onnx.dynamo_export`, we need to avoid to check the contents of the mask;
|
| 323 |
+
# otherwise, we will encounter dynamic control flows
|
| 324 |
+
if (
|
| 325 |
+
not is_tracing(padding_mask)
|
| 326 |
+
and (padding_mask is None or padding_mask.all())
|
| 327 |
+
# in this case we need to add special patterns to the mask so cannot be skipped otherwise
|
| 328 |
+
and (local_attention_size is None or kv_length < local_attention_size)
|
| 329 |
+
):
|
| 330 |
+
return True
|
| 331 |
+
|
| 332 |
+
return False
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
def _vmap_expansion_sdpa(mask_function: Callable) -> Callable:
|
| 336 |
+
"""
|
| 337 |
+
Used to vmap our mask_functions over the all 4 dimensions (b_idx, h_idx, q_idx, kv_idx) of the inputs.
|
| 338 |
+
Using vmap here allows us to keep the performance of vectorized ops, while having a single set of primitive
|
| 339 |
+
functions between attention interfaces (i.e. between flex and sdpa/eager, FA2 being a bit different).
|
| 340 |
+
"""
|
| 341 |
+
# We vmap the function over all 4 dimensions, broadcasting [b_idx, h_idx, q_idx, kv_idx]
|
| 342 |
+
dimensions = [(None, None, None, 0), (None, None, 0, None), (None, 0, None, None), (0, None, None, None)]
|
| 343 |
+
for dims in dimensions:
|
| 344 |
+
mask_function = torch.vmap(mask_function, in_dims=dims, out_dims=0)
|
| 345 |
+
return mask_function
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
def _non_vmap_expansion_sdpa(
|
| 349 |
+
batch_indices: torch.Tensor, head_indices: torch.Tensor, q_indices: torch.Tensor, kv_indices: torch.Tensor
|
| 350 |
+
):
|
| 351 |
+
"""
|
| 352 |
+
Used to broadcast our mask_functions over the all 4 dimensions (b_idx, h_idx, q_idx, kv_idx) of the inputs.
|
| 353 |
+
Allows the usage of any index-based mask function without relying on vmap.
|
| 354 |
+
|
| 355 |
+
NOTE: This is limited to index based functions only and is not guaranteed to work otherwise.
|
| 356 |
+
|
| 357 |
+
Reference:
|
| 358 |
+
- https://github.com/huggingface/optimum-onnx/blob/c123e8f4fab61b54a8e0e31ce74462bcacca576e/optimum/exporters/onnx/model_patcher.py#L362-L365
|
| 359 |
+
"""
|
| 360 |
+
batch_indices = batch_indices[:, None, None, None]
|
| 361 |
+
head_indices = head_indices[None, :, None, None]
|
| 362 |
+
q_indices = q_indices[None, None, :, None]
|
| 363 |
+
kv_indices = kv_indices[None, None, None, :]
|
| 364 |
+
return batch_indices, head_indices, q_indices, kv_indices
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
def sdpa_mask(
|
| 368 |
+
batch_size: int,
|
| 369 |
+
q_length: int,
|
| 370 |
+
kv_length: int,
|
| 371 |
+
q_offset: int = 0,
|
| 372 |
+
kv_offset: int = 0,
|
| 373 |
+
mask_function: Callable = causal_mask_function,
|
| 374 |
+
attention_mask: torch.Tensor | None = None,
|
| 375 |
+
local_size: int | None = None,
|
| 376 |
+
allow_is_causal_skip: bool = True,
|
| 377 |
+
allow_is_bidirectional_skip: bool = False,
|
| 378 |
+
allow_torch_fix: bool = True,
|
| 379 |
+
use_vmap: bool = False,
|
| 380 |
+
device: torch.device | str = "cpu",
|
| 381 |
+
**kwargs,
|
| 382 |
+
) -> torch.Tensor | None:
|
| 383 |
+
"""
|
| 384 |
+
Create a 4D boolean mask of shape `(batch_size, 1, query_length, kv_length)` where a value of True indicates that
|
| 385 |
+
the element should take part in the attention computation, and False that it should not.
|
| 386 |
+
This function can only be used with torch>=2.5, as the context manager is otherwise not available.
|
| 387 |
+
|
| 388 |
+
Args:
|
| 389 |
+
batch_size (`int`):
|
| 390 |
+
The batch size of the input sequence.
|
| 391 |
+
q_length (`int`):
|
| 392 |
+
The size that the query states will have during the attention computation.
|
| 393 |
+
kv_length (`int`):
|
| 394 |
+
The size that the key and value states will have during the attention computation.
|
| 395 |
+
kv_offset (`int`, optional):
|
| 396 |
+
An optional offset to indicate at which first position the key and values states will refer to.
|
| 397 |
+
q_offset (`int`, optional):
|
| 398 |
+
An optional offset to indicate at which first position the query states will refer to.
|
| 399 |
+
mask_function (`Callable`):
|
| 400 |
+
The mask factory function describing the mask pattern.
|
| 401 |
+
attention_mask (`torch.Tensor`, optional):
|
| 402 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
|
| 403 |
+
local_size (`int`, optional):
|
| 404 |
+
The size of the local attention, if we do not use full attention. This is used only if `allow_is_causal_skip=True`
|
| 405 |
+
to try to skip mask creation if possible.
|
| 406 |
+
allow_is_causal_skip (`bool`, optional):
|
| 407 |
+
Whether to allow to return `None` for the mask under conditions where we can use the `is_causal` argument in
|
| 408 |
+
`torch.sdpa` instead. Default to `True`.
|
| 409 |
+
allow_is_bidirectional_skip (`bool`, optional):
|
| 410 |
+
Whether to allow to return `None` for the mask under conditions where we do not have to add any bias,
|
| 411 |
+
i.e. full attention without any padding. Default to `False`.
|
| 412 |
+
allow_torch_fix (`bool`, optional):
|
| 413 |
+
Whether to update the mask in case a query is not attending to any tokens, to solve a bug in torch's older
|
| 414 |
+
versions. We need an arg to skip it when using eager. By default `True`.
|
| 415 |
+
use_vmap (`bool`, optional):
|
| 416 |
+
Whether to use `vmap` during the mask construction or not. Allows powerful custom patterns that may not be
|
| 417 |
+
index-based (for the cost of speed performance). By default `False`.
|
| 418 |
+
device (`torch.device` or `str`, optional):
|
| 419 |
+
An optional device to create the mask on.
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
## Creating a simple causal mask:
|
| 423 |
+
|
| 424 |
+
To create the following causal mask:
|
| 425 |
+
|
| 426 |
+
0 ■ ⬚ ⬚ ⬚ ⬚
|
| 427 |
+
1 ■ ■ ⬚ ⬚ ⬚
|
| 428 |
+
2 ■ ■ ■ ⬚ ⬚
|
| 429 |
+
3 ■ ■ ■ ■ ⬚
|
| 430 |
+
4 ■ ■ ■ ■ ■
|
| 431 |
+
|
| 432 |
+
You can do
|
| 433 |
+
|
| 434 |
+
```python
|
| 435 |
+
>>> sdpa_mask(batch_size=1, q_length=5, kv_length=5)
|
| 436 |
+
>>> tensor([[[[ True, False, False, False, False],
|
| 437 |
+
[ True, True, False, False, False],
|
| 438 |
+
[ True, True, True, False, False],
|
| 439 |
+
[ True, True, True, True, False],
|
| 440 |
+
[ True, True, True, True, True]]]])
|
| 441 |
+
```
|
| 442 |
+
|
| 443 |
+
## Creating a sliding window mask:
|
| 444 |
+
|
| 445 |
+
To create the following sliding window mask (`sliding_window=3`):
|
| 446 |
+
|
| 447 |
+
0 ■ ⬚ ⬚ ⬚ ⬚
|
| 448 |
+
1 ■ ■ ⬚ ⬚ ⬚
|
| 449 |
+
2 ■ ■ ■ ⬚ ⬚
|
| 450 |
+
3 ⬚ ■ ■ ■ ⬚
|
| 451 |
+
4 ⬚ ⬚ ■ ■ ■
|
| 452 |
+
|
| 453 |
+
You can do
|
| 454 |
+
|
| 455 |
+
```python
|
| 456 |
+
>>> sdpa_mask(batch_size=1, q_length=5, kv_length=5, mask_function=sliding_window_causal_mask_function(3))
|
| 457 |
+
>>> tensor([[[[ True, False, False, False, False],
|
| 458 |
+
[ True, True, False, False, False],
|
| 459 |
+
[ True, True, True, False, False],
|
| 460 |
+
[False, True, True, True, False],
|
| 461 |
+
[False, False, True, True, True]]]])
|
| 462 |
+
```
|
| 463 |
+
|
| 464 |
+
## Creating a chunked attention mask
|
| 465 |
+
|
| 466 |
+
To create the following chunked attention mask (`chunk_size=3`):
|
| 467 |
+
|
| 468 |
+
0 ■ ⬚ ⬚ ⬚ ⬚
|
| 469 |
+
1 ■ ■ ⬚ ⬚ ⬚
|
| 470 |
+
2 ■ ■ ■ ⬚ ⬚
|
| 471 |
+
3 ⬚ ⬚ ⬚ ■ ⬚
|
| 472 |
+
4 ⬚ ⬚ ⬚ ■ ■
|
| 473 |
+
|
| 474 |
+
You can do
|
| 475 |
+
|
| 476 |
+
```python
|
| 477 |
+
>>> sdpa_mask(batch_size=1, q_length=5, kv_length=5, mask_function=chunked_causal_mask_function(3, torch.zeros(1, dtype=int)))
|
| 478 |
+
>>> tensor([[[[ True, False, False, False, False],
|
| 479 |
+
[ True, True, False, False, False],
|
| 480 |
+
[ True, True, True, False, False],
|
| 481 |
+
[False, False, False, True, False],
|
| 482 |
+
[False, False, False, True, True]]]])
|
| 483 |
+
```
|
| 484 |
+
|
| 485 |
+
"""
|
| 486 |
+
# For BC on `cache_positions` that used to be an arg at the position of `q_length`
|
| 487 |
+
if isinstance(q_length, torch.Tensor):
|
| 488 |
+
logger.warning_once(
|
| 489 |
+
"`cache_position` is deprecated as an arg, and will be removed in Transformers v5.6. Please use `q_length` and "
|
| 490 |
+
"`q_offset` instead, similarly to `kv_length` and `kv_offset`"
|
| 491 |
+
)
|
| 492 |
+
q_length, q_offset = q_length.shape[0], q_length[0].to(device)
|
| 493 |
+
|
| 494 |
+
# Potentially pad the 2D mask
|
| 495 |
+
padding_mask = prepare_padding_mask(attention_mask, kv_length, kv_offset)
|
| 496 |
+
|
| 497 |
+
# Under specific conditions, we can avoid materializing the mask
|
| 498 |
+
# 1. Causal masks can rely on the `is_causal` argument
|
| 499 |
+
# 2. Bidirectional do not need any further processing (no bias)
|
| 500 |
+
if allow_is_causal_skip and _ignore_causal_mask_sdpa(padding_mask, q_length, kv_length, kv_offset, local_size):
|
| 501 |
+
return None
|
| 502 |
+
if allow_is_bidirectional_skip and _ignore_bidirectional_mask_sdpa(padding_mask, kv_length, local_size):
|
| 503 |
+
return None
|
| 504 |
+
|
| 505 |
+
# Potentially add the padding 2D mask
|
| 506 |
+
if padding_mask is not None:
|
| 507 |
+
mask_function = and_masks(mask_function, padding_mask_function(padding_mask))
|
| 508 |
+
|
| 509 |
+
batch_arange = torch.arange(batch_size, device=device)
|
| 510 |
+
head_arange = torch.arange(1, device=device)
|
| 511 |
+
q_arange = torch.arange(q_length, device=device) + q_offset
|
| 512 |
+
kv_arange = torch.arange(kv_length, device=device) + kv_offset
|
| 513 |
+
|
| 514 |
+
# Actual mask creation
|
| 515 |
+
# Option 1: Fast non-vmap mask creation (default)
|
| 516 |
+
if not use_vmap:
|
| 517 |
+
# Apply mask function element-wise through broadcasting
|
| 518 |
+
attention_mask = mask_function(*_non_vmap_expansion_sdpa(batch_arange, head_arange, q_arange, kv_arange))
|
| 519 |
+
# Expand the mask to match batch size and query length if they weren't used in the mask function
|
| 520 |
+
attention_mask = attention_mask.expand(batch_size, -1, q_length, kv_length)
|
| 521 |
+
|
| 522 |
+
# Option 2: Vmap mask creation (torch>=2.6 and custom patterns)
|
| 523 |
+
elif _is_torch_greater_or_equal_than_2_6:
|
| 524 |
+
# This creates the 4D mask easily. Note that we need this context manager as vmap cannot handle slicing a tensor from
|
| 525 |
+
# scalar tensor (it internally calls `.item()` which vmap does not allow, but this context works around it
|
| 526 |
+
# We don't need to add an offset to the mask_function either, as we vmap directly the correct indices for k and kv indices
|
| 527 |
+
with TransformGetItemToIndex():
|
| 528 |
+
attention_mask = _vmap_expansion_sdpa(mask_function)(batch_arange, head_arange, q_arange, kv_arange)
|
| 529 |
+
|
| 530 |
+
# Option 3: Error out since it indicates that the user did something custom, which they shouldn't have (torch<2.6)
|
| 531 |
+
else:
|
| 532 |
+
raise ValueError(
|
| 533 |
+
"The vmap functionality for mask creation is only supported from torch>=2.6. "
|
| 534 |
+
"Please update your torch version or use `use_vmap=False` with index-based masks."
|
| 535 |
+
)
|
| 536 |
+
|
| 537 |
+
# Due to a bug in versions of torch<2.5, we need to update the mask in case a query is not attending to any
|
| 538 |
+
# tokens (due to padding). See details in https://github.com/pytorch/pytorch/issues/110213
|
| 539 |
+
if not _is_torch_greater_or_equal_than_2_5 and allow_torch_fix:
|
| 540 |
+
attention_mask = attention_mask | torch.all(~attention_mask, dim=-1, keepdim=True)
|
| 541 |
+
|
| 542 |
+
return attention_mask
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
def eager_mask(
|
| 546 |
+
batch_size: int,
|
| 547 |
+
q_length: int,
|
| 548 |
+
kv_length: int,
|
| 549 |
+
q_offset: int = 0,
|
| 550 |
+
kv_offset: int = 0,
|
| 551 |
+
mask_function: Callable = causal_mask_function,
|
| 552 |
+
attention_mask: torch.Tensor | None = None,
|
| 553 |
+
dtype: torch.dtype = torch.float32,
|
| 554 |
+
allow_is_bidirectional_skip: bool = False,
|
| 555 |
+
use_vmap: bool = False,
|
| 556 |
+
device: torch.device | str = "cpu",
|
| 557 |
+
**kwargs,
|
| 558 |
+
) -> torch.Tensor:
|
| 559 |
+
"""
|
| 560 |
+
Create a 4D float mask of shape `(batch_size, 1, query_length, kv_length)` where a value of 0 indicates that
|
| 561 |
+
the element should take part in the attention computation, and -inf (minimum value for the given `dtype`) that
|
| 562 |
+
it should not.
|
| 563 |
+
|
| 564 |
+
Args:
|
| 565 |
+
batch_size (`int`):
|
| 566 |
+
The batch size of the input sequence.
|
| 567 |
+
q_length (`int`):
|
| 568 |
+
The size that the query states will have during the attention computation.
|
| 569 |
+
kv_length (`int`):
|
| 570 |
+
The size that the key and value states will have during the attention computation.
|
| 571 |
+
q_offset (`int`, optional):
|
| 572 |
+
An optional offset to indicate at which first position the query states will refer to.
|
| 573 |
+
kv_offset (`int`, optional):
|
| 574 |
+
An optional offset to indicate at which first position the key and values states will refer to.
|
| 575 |
+
mask_function (`Callable`):
|
| 576 |
+
The mask factory function describing the mask pattern.
|
| 577 |
+
attention_mask (`torch.Tensor`, optional):
|
| 578 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
|
| 579 |
+
dtype (`torch.dtype`, optional):
|
| 580 |
+
The dtype to use for the mask. By default, `torch.float32`.
|
| 581 |
+
allow_is_bidirectional_skip (`bool`, optional):
|
| 582 |
+
Whether to allow to return `None` for the mask under conditions where we do not have to add any bias,
|
| 583 |
+
i.e. full attention without any padding. Default to `False`.
|
| 584 |
+
use_vmap (`bool`, optional):
|
| 585 |
+
Whether to use `vmap` during the mask construction or not. Allows powerful custom patterns that may not be
|
| 586 |
+
index-based (for the cost of speed performance). By default `False`.
|
| 587 |
+
device (`torch.device` or `str`, optional):
|
| 588 |
+
An optional device to create the mask on.
|
| 589 |
+
"""
|
| 590 |
+
# The masks for eager attention are simply boolean mask from sdpa, casted to 0 and -inf
|
| 591 |
+
_ = kwargs.pop("allow_is_causal_skip", None)
|
| 592 |
+
_ = kwargs.pop("allow_torch_fix", None)
|
| 593 |
+
mask = sdpa_mask(
|
| 594 |
+
batch_size=batch_size,
|
| 595 |
+
q_length=q_length,
|
| 596 |
+
kv_length=kv_length,
|
| 597 |
+
q_offset=q_offset,
|
| 598 |
+
kv_offset=kv_offset,
|
| 599 |
+
mask_function=mask_function,
|
| 600 |
+
attention_mask=attention_mask,
|
| 601 |
+
allow_is_causal_skip=False,
|
| 602 |
+
allow_is_bidirectional_skip=allow_is_bidirectional_skip,
|
| 603 |
+
allow_torch_fix=False,
|
| 604 |
+
use_vmap=use_vmap,
|
| 605 |
+
device=device,
|
| 606 |
+
**kwargs,
|
| 607 |
+
)
|
| 608 |
+
# only bidirectional masks can be skipped, otherwise we convert bool -> float
|
| 609 |
+
if mask is not None:
|
| 610 |
+
min_dtype = torch.finfo(dtype).min
|
| 611 |
+
# we need 0s where the tokens should be taken into account, and -inf otherwise (mask is already of boolean type)
|
| 612 |
+
mask = torch.where(mask, torch.tensor(0.0, device=mask.device, dtype=dtype), min_dtype)
|
| 613 |
+
return mask
|
| 614 |
+
|
| 615 |
+
|
| 616 |
+
def flash_attention_mask(
|
| 617 |
+
batch_size: int,
|
| 618 |
+
q_length: int,
|
| 619 |
+
kv_length: int,
|
| 620 |
+
q_offset: int = 0,
|
| 621 |
+
kv_offset: int = 0,
|
| 622 |
+
mask_function: Callable = causal_mask_function,
|
| 623 |
+
attention_mask: torch.Tensor | None = None,
|
| 624 |
+
**kwargs,
|
| 625 |
+
):
|
| 626 |
+
"""
|
| 627 |
+
Create the attention mask necessary to use FA2. Since FA2 is un-padded by definition, here we simply return
|
| 628 |
+
`None` if the mask is fully causal, or we return the 2D mask which will then be used to extract the seq_lens.
|
| 629 |
+
We just slice it in case of sliding window.
|
| 630 |
+
|
| 631 |
+
Args:
|
| 632 |
+
batch_size (`int`):
|
| 633 |
+
The batch size of the input sequence.
|
| 634 |
+
q_length (`int`):
|
| 635 |
+
The size that the query states will have during the attention computation.
|
| 636 |
+
kv_length (`int`):
|
| 637 |
+
The size that the key and value states will have during the attention computation.
|
| 638 |
+
q_offset (`int`, optional):
|
| 639 |
+
An optional offset to indicate at which first position the query states will refer to.
|
| 640 |
+
kv_offset (`int`, optional):
|
| 641 |
+
An optional offset to indicate at which first position the key and values states will refer to.
|
| 642 |
+
mask_function (`Callable`):
|
| 643 |
+
The mask factory function describing the mask pattern.
|
| 644 |
+
attention_mask (`torch.Tensor`, optional):
|
| 645 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
|
| 646 |
+
"""
|
| 647 |
+
if attention_mask is not None:
|
| 648 |
+
# Here we need to slice from the right if using sliding or chunked (for full attention, this is equivalent to doing nothing)
|
| 649 |
+
attention_mask = attention_mask[:, -kv_length:]
|
| 650 |
+
# We only return an actual mask if there is at least 1 padding token, otherwise we return `None` and use `is_causal` in FA2
|
| 651 |
+
# (note that the attention_mask is a boolean dtype here)
|
| 652 |
+
if attention_mask.all():
|
| 653 |
+
attention_mask = None
|
| 654 |
+
|
| 655 |
+
return attention_mask
|
| 656 |
+
|
| 657 |
+
|
| 658 |
+
def flex_attention_mask(
|
| 659 |
+
batch_size: int,
|
| 660 |
+
q_length: int,
|
| 661 |
+
kv_length: int,
|
| 662 |
+
q_offset: int = 0,
|
| 663 |
+
kv_offset: int = 0,
|
| 664 |
+
mask_function: Callable = causal_mask_function,
|
| 665 |
+
attention_mask: torch.Tensor | None = None,
|
| 666 |
+
device: torch.device | str = "cpu",
|
| 667 |
+
**kwargs,
|
| 668 |
+
) -> BlockMask:
|
| 669 |
+
"""
|
| 670 |
+
Create a 4D block mask which is a compressed representation of the full 4D block causal mask. BlockMask is essential
|
| 671 |
+
for performant computation of flex attention. See: https://pytorch.org/blog/flexattention/
|
| 672 |
+
|
| 673 |
+
Args:
|
| 674 |
+
batch_size (`int`):
|
| 675 |
+
The batch size of the input sequence.
|
| 676 |
+
q_length (`int`):
|
| 677 |
+
The size that the query states will have during the attention computation.
|
| 678 |
+
kv_length (`int`):
|
| 679 |
+
The size that the key and value states will have during the attention computation.
|
| 680 |
+
q_offset (`int`, optional):
|
| 681 |
+
An optional offset to indicate at which first position the query states will refer to.
|
| 682 |
+
kv_offset (`int`, optional):
|
| 683 |
+
An optional offset to indicate at which first position the key and values states will refer to.
|
| 684 |
+
mask_function (`Callable`):
|
| 685 |
+
The mask factory function describing the mask pattern.
|
| 686 |
+
attention_mask (`torch.Tensor`, optional):
|
| 687 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length)
|
| 688 |
+
device (`torch.device` or `str`, optional):
|
| 689 |
+
An optional device to create the mask on.
|
| 690 |
+
"""
|
| 691 |
+
# For BC on `cache_positions` that used to be an arg at the position of `q_length`
|
| 692 |
+
if isinstance(q_length, torch.Tensor):
|
| 693 |
+
logger.warning_once(
|
| 694 |
+
"`cache_position` is deprecated as an arg, and will be removed in Transformers v5.6. Please use `q_length` and "
|
| 695 |
+
"`q_offset` instead, similarly to `kv_length` and `kv_offset`"
|
| 696 |
+
)
|
| 697 |
+
q_length, q_offset = q_length.shape[0], q_length[0].to(device)
|
| 698 |
+
|
| 699 |
+
# Potentially add the padding 2D mask
|
| 700 |
+
if attention_mask is not None:
|
| 701 |
+
# Older torch (2.5.x) cannot handle sequences not in multiples of 128 (default block size)
|
| 702 |
+
# Hence we pad to multiples of this as a minimum to ensure this
|
| 703 |
+
pad_len = ((attention_mask.shape[1] // flex_default_block_size) + 1) * flex_default_block_size
|
| 704 |
+
pad_len = pad_len - attention_mask.shape[1]
|
| 705 |
+
if not _is_torch_greater_or_equal_than_2_6 and pad_len > 0:
|
| 706 |
+
attention_mask = torch.nn.functional.pad(attention_mask, value=0, pad=(0, pad_len))
|
| 707 |
+
|
| 708 |
+
padding_mask = prepare_padding_mask(attention_mask, kv_length, kv_offset)
|
| 709 |
+
mask_function = and_masks(mask_function, padding_mask_function(padding_mask))
|
| 710 |
+
|
| 711 |
+
# Add the offsets on top (because flex interface only allows length, not start and end indices)
|
| 712 |
+
mask_function = add_offsets_to_mask_function(mask_function, q_offset, kv_offset)
|
| 713 |
+
|
| 714 |
+
# Finally create the block mask
|
| 715 |
+
block_mask = create_block_mask(
|
| 716 |
+
mask_mod=mask_function,
|
| 717 |
+
B=batch_size,
|
| 718 |
+
H=None,
|
| 719 |
+
Q_LEN=q_length,
|
| 720 |
+
KV_LEN=kv_length,
|
| 721 |
+
device=device,
|
| 722 |
+
_compile=_is_torch_greater_or_equal_than_2_6,
|
| 723 |
+
)
|
| 724 |
+
return block_mask
|
| 725 |
+
|
| 726 |
+
|
| 727 |
+
class AttentionMaskInterface(GeneralInterface):
|
| 728 |
+
# Class instance object, so that a call to `register` can be reflected into all other files correctly, even if
|
| 729 |
+
# a new instance is created (in order to locally override a given function)
|
| 730 |
+
_global_mapping = {
|
| 731 |
+
"sdpa": sdpa_mask,
|
| 732 |
+
"eager": eager_mask,
|
| 733 |
+
"flash_attention_2": flash_attention_mask,
|
| 734 |
+
"flash_attention_3": flash_attention_mask,
|
| 735 |
+
"flash_attention_4": flash_attention_mask,
|
| 736 |
+
"flex_attention": flex_attention_mask,
|
| 737 |
+
}
|
| 738 |
+
|
| 739 |
+
|
| 740 |
+
# Global AttentionMaskInterface shared by all models which do not need to overwrite any of the existing ones
|
| 741 |
+
ALL_MASK_ATTENTION_FUNCTIONS: AttentionMaskInterface = AttentionMaskInterface()
|
| 742 |
+
|
| 743 |
+
|
| 744 |
+
def find_packed_sequence_indices(position_ids: torch.Tensor) -> torch.Tensor | None:
|
| 745 |
+
"""
|
| 746 |
+
Find the indices of the sequence to which each new query token in the sequence belongs when using packed
|
| 747 |
+
tensor format (i.e. several sequences packed in the same batch dimension).
|
| 748 |
+
|
| 749 |
+
Args:
|
| 750 |
+
position_ids (`torch.Tensor`)
|
| 751 |
+
A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
|
| 752 |
+
|
| 753 |
+
Returns:
|
| 754 |
+
A 2D tensor where each similar integer indicates that the tokens belong to the same sequence. For example, if we
|
| 755 |
+
pack 3 sequences of 2, 3 and 1 tokens respectively along a single batch dim, this will return [[0, 0, 1, 1, 1, 2]].
|
| 756 |
+
|
| 757 |
+
If the there is only one sequence in each batch item (and we don't compile), then we return `None` indicating
|
| 758 |
+
no packed sequences. This is the same as [[0, 0, 0, 0, 0, 0]] for the example above.
|
| 759 |
+
"""
|
| 760 |
+
# What separate different sequences is when 2 consecutive positions_ids are separated by more than 1. So
|
| 761 |
+
# taking the diff (by prepending the first value - 1 to keep correct indexing) and applying cumsum to the result
|
| 762 |
+
# gives exactly the sequence indices
|
| 763 |
+
# Note that we assume that a single sequence cannot span several batch dimensions, i.e. 1 single sequence
|
| 764 |
+
# cannot be part of the end of the first batch dim and the start of the 2nd one for example
|
| 765 |
+
first_dummy_value = position_ids[:, :1] - 1 # We just need the diff on this first value to be 1
|
| 766 |
+
position_diff = torch.diff(position_ids, prepend=first_dummy_value, dim=-1)
|
| 767 |
+
packed_sequence_mask = (position_diff != 1).cumsum(-1)
|
| 768 |
+
|
| 769 |
+
# Sadly this is a dynamic control flow, so we cannot enable this check on anything compile related
|
| 770 |
+
if not is_tracing(packed_sequence_mask) and (packed_sequence_mask[:, -1] == 0).all():
|
| 771 |
+
return None
|
| 772 |
+
|
| 773 |
+
return packed_sequence_mask
|
| 774 |
+
|
| 775 |
+
|
| 776 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 777 |
+
def _preprocess_mask_arguments(
|
| 778 |
+
config: PreTrainedConfig,
|
| 779 |
+
inputs_embeds: torch.Tensor,
|
| 780 |
+
attention_mask: torch.Tensor | BlockMask | None,
|
| 781 |
+
past_key_values: Cache | None,
|
| 782 |
+
position_ids: torch.Tensor | None,
|
| 783 |
+
layer_idx: int | None,
|
| 784 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 785 |
+
) -> tuple[bool, torch.Tensor | BlockMask | None, int, int]:
|
| 786 |
+
"""
|
| 787 |
+
Perform some common pre-processing of the mask arguments we get from the modeling code. Mostly determine the
|
| 788 |
+
key-value length and offsets, and if we should early exit or not.
|
| 789 |
+
|
| 790 |
+
Args:
|
| 791 |
+
config (`PreTrainedConfig`):
|
| 792 |
+
The model config.
|
| 793 |
+
inputs_embeds (`torch.Tensor`):
|
| 794 |
+
The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
|
| 795 |
+
batch size, query length and dtype.
|
| 796 |
+
attention_mask (`torch.Tensor`, optional):
|
| 797 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
|
| 798 |
+
It can also be an already prepared 4D mask, in which case it is returned as-is.
|
| 799 |
+
past_key_values (`Cache`, optional):
|
| 800 |
+
The past key values, if we use a cache.
|
| 801 |
+
position_ids (`torch.Tensor`, optional)
|
| 802 |
+
A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
|
| 803 |
+
layer_idx (`int`, optional):
|
| 804 |
+
If `past_key_values` is not None, this is the layer index of the cache from which to get the key-value
|
| 805 |
+
length and offset. Indeed, for hybrid caches, different layers may return different lengths.
|
| 806 |
+
encoder_hidden_states (`torch.Tensor`, optional):
|
| 807 |
+
The input embeddings of shape (batch_size, kv_length, hidden_dim). If provided, it is used instead of
|
| 808 |
+
`inputs_embeds` to infer the kv length.
|
| 809 |
+
|
| 810 |
+
Returns:
|
| 811 |
+
early_exit (`bool`):
|
| 812 |
+
Whether we should early exit mask creation, and return the mask as-is.
|
| 813 |
+
attention_mask (`torch.Tensor` or `BlockMask` or `None`):
|
| 814 |
+
The attention mask to either return immediately, or to use in downstream mask creation.
|
| 815 |
+
packed_sequence_mask (`torch.Tensor`, optional):
|
| 816 |
+
In case we detected packed sequence format, this is a tensor where each similar integer indicates that
|
| 817 |
+
the tokens belong to the same sequence.
|
| 818 |
+
q_length (`int`):
|
| 819 |
+
The size that the query states will have during the attention computation.
|
| 820 |
+
kv_length (`int`):
|
| 821 |
+
The size that the key and value states will have during the attention computation.
|
| 822 |
+
q_offset (`int`, optional):
|
| 823 |
+
An optional offset to indicate at which first position the query states will refer to.
|
| 824 |
+
kv_offset (`int`):
|
| 825 |
+
An offset to indicate at which first position the key and values states will refer to.
|
| 826 |
+
"""
|
| 827 |
+
# If the mask is already 4D, simply return as-is (it was already prepared, or it is custom)
|
| 828 |
+
if isinstance(attention_mask, (torch.Tensor, BlockMask)) and len(attention_mask.shape) == 4:
|
| 829 |
+
return True, attention_mask, None, None, None, None, None
|
| 830 |
+
|
| 831 |
+
# For TGI/vLLM backends, or other custom attention without equivalent mask creation: we don't need a mask!
|
| 832 |
+
# Note: it's not ideal to check the `_global_mapping` attribute instead of the object itself, however otherwise
|
| 833 |
+
# full graph dynamo tracing (i.e. torch.export or compile with `fullgraph=True`) will fail on Python<3.11
|
| 834 |
+
# with `torch._dynamo.exc.Unsupported: 'inline in skipfiles:Mapping.__contains__ | __contains__, skipped
|
| 835 |
+
# according trace_rules.lookup SKIP_DIRS'` -- can be removed when we require Python>=3.11
|
| 836 |
+
if config._attn_implementation not in ALL_MASK_ATTENTION_FUNCTIONS._global_mapping:
|
| 837 |
+
return True, None, None, None, None, None, None
|
| 838 |
+
|
| 839 |
+
# Move the mask to correct device, and potentially switch dtype for efficiency
|
| 840 |
+
if attention_mask is not None and attention_mask.ndim == 2:
|
| 841 |
+
attention_mask = attention_mask.to(device=inputs_embeds.device, dtype=torch.bool)
|
| 842 |
+
|
| 843 |
+
q_length = inputs_embeds.shape[1]
|
| 844 |
+
# If using a cache, it can give all information about mask sizes based on seen tokens
|
| 845 |
+
if past_key_values is not None:
|
| 846 |
+
q_offset = past_key_values.get_seq_length()
|
| 847 |
+
# To avoid graph breaks, StaticLayer return a tensor instead of int -> this has no impact on the ops, but we
|
| 848 |
+
# need the correct device
|
| 849 |
+
q_offset = q_offset.to(inputs_embeds.device) if isinstance(q_offset, torch.Tensor) else q_offset
|
| 850 |
+
kv_length, kv_offset = past_key_values.get_mask_sizes(q_length, layer_idx)
|
| 851 |
+
# Otherwise, we infer based on our input
|
| 852 |
+
else:
|
| 853 |
+
q_offset = 0
|
| 854 |
+
# 1. Rely on input directly
|
| 855 |
+
if attention_mask is None:
|
| 856 |
+
# For encoder-decoders, use encoder_hidden_states to infer kv_length if provided
|
| 857 |
+
kv_length = encoder_hidden_states.shape[1] if encoder_hidden_states is not None else q_length
|
| 858 |
+
kv_offset = 0
|
| 859 |
+
# 2. Rely on the mask instead - needed for special cases like prefix tuning in PEFT
|
| 860 |
+
#
|
| 861 |
+
# This is a very unique and special case where an encoder utilizes a cache and expects its length
|
| 862 |
+
# to be accounted for (usually, they should never use a cache). In general, the mask should always
|
| 863 |
+
# match with the input sizes nonetheless (i.e. it does not affect others).
|
| 864 |
+
# Conclusion: "prefix tuning is evil"
|
| 865 |
+
else:
|
| 866 |
+
kv_length, kv_offset = attention_mask.shape[-1], 0
|
| 867 |
+
|
| 868 |
+
# We check the position_ids for potential packed sequence format (only if the 2D attention mask is explicitly None,
|
| 869 |
+
# and we don't have past_key_values, i.e. generally a training setup)
|
| 870 |
+
packed_sequence_mask = None
|
| 871 |
+
if position_ids is not None and attention_mask is None and past_key_values is None:
|
| 872 |
+
batch_size = inputs_embeds.shape[0]
|
| 873 |
+
# The position ids are sometimes just unsqueezed, without being expanded
|
| 874 |
+
if batch_size != position_ids.shape[0]:
|
| 875 |
+
position_ids = position_ids.expand(batch_size, -1)
|
| 876 |
+
packed_sequence_mask = find_packed_sequence_indices(position_ids)
|
| 877 |
+
|
| 878 |
+
return False, attention_mask, packed_sequence_mask, q_length, kv_length, q_offset, kv_offset
|
| 879 |
+
|
| 880 |
+
|
| 881 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 882 |
+
def create_causal_mask(
|
| 883 |
+
config: PreTrainedConfig,
|
| 884 |
+
inputs_embeds: torch.Tensor,
|
| 885 |
+
attention_mask: torch.Tensor | None,
|
| 886 |
+
cache_position: torch.Tensor | None = None, # not used anymore but kept for BC
|
| 887 |
+
*,
|
| 888 |
+
past_key_values: Cache | None,
|
| 889 |
+
position_ids: torch.Tensor | None = None,
|
| 890 |
+
or_mask_function: Callable | None = None,
|
| 891 |
+
and_mask_function: Callable | None = None,
|
| 892 |
+
) -> torch.Tensor | BlockMask | None:
|
| 893 |
+
"""
|
| 894 |
+
Create a standard causal mask based on the attention implementation used (stored in the config). If `past_key_values`
|
| 895 |
+
has an hybrid cache structure, this function will return the mask corresponding to one of the "full_attention" layers (to align
|
| 896 |
+
to what is needed in the `modeling_xxx.py` files).
|
| 897 |
+
|
| 898 |
+
Args:
|
| 899 |
+
config (`PreTrainedConfig`):
|
| 900 |
+
The model config.
|
| 901 |
+
inputs_embeds (`torch.Tensor`):
|
| 902 |
+
The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
|
| 903 |
+
batch size, query length and dtype.
|
| 904 |
+
attention_mask (`torch.Tensor`, optional):
|
| 905 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
|
| 906 |
+
It can also be an already prepared 4D mask, in which case it is returned as-is.
|
| 907 |
+
cache_position (`torch.Tensor`):
|
| 908 |
+
Deprecated and unused.
|
| 909 |
+
past_key_values (`Cache`, optional):
|
| 910 |
+
The past key values, if we use a cache.
|
| 911 |
+
position_ids (`torch.Tensor`, optional)
|
| 912 |
+
A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
|
| 913 |
+
or_mask_function (`Callable`, optional):
|
| 914 |
+
An optional mask function to combine with the causal mask function (by doing the union of both). This is
|
| 915 |
+
useful to easily overlay another mask on top of the causal one, for example for image tokens handling.
|
| 916 |
+
and_mask_function (`Callable`, optional):
|
| 917 |
+
An optional mask function to combine with the causal mask function (by doing the intersection of both). This is
|
| 918 |
+
useful to easily overlay another mask on top of the causal one, for example for image tokens handling.
|
| 919 |
+
"""
|
| 920 |
+
# Power feature: if `is_causal` is False, then fallback to bi-directional mask for bi-directional attention.
|
| 921 |
+
# It allows to use decoder-only models with bi-directional attention as well
|
| 922 |
+
if not getattr(config, "is_causal", True):
|
| 923 |
+
return create_bidirectional_mask(
|
| 924 |
+
config,
|
| 925 |
+
inputs_embeds,
|
| 926 |
+
attention_mask,
|
| 927 |
+
past_key_values=past_key_values,
|
| 928 |
+
or_mask_function=or_mask_function,
|
| 929 |
+
and_mask_function=and_mask_function,
|
| 930 |
+
)
|
| 931 |
+
|
| 932 |
+
# If we have an hybrid cache structure, here we want to create the mask for the full layers
|
| 933 |
+
if hasattr(past_key_values, "is_sliding") and False in past_key_values.is_sliding:
|
| 934 |
+
layer_idx = past_key_values.is_sliding.index(False)
|
| 935 |
+
else:
|
| 936 |
+
layer_idx = 0
|
| 937 |
+
|
| 938 |
+
early_exit, attention_mask, packed_sequence_mask, q_length, kv_length, q_offset, kv_offset = (
|
| 939 |
+
_preprocess_mask_arguments(config, inputs_embeds, attention_mask, past_key_values, position_ids, layer_idx)
|
| 940 |
+
)
|
| 941 |
+
if early_exit:
|
| 942 |
+
return attention_mask
|
| 943 |
+
|
| 944 |
+
batch_size, dtype, device = inputs_embeds.shape[0], inputs_embeds.dtype, inputs_embeds.device
|
| 945 |
+
mask_factory_function = causal_mask_function
|
| 946 |
+
mask_interface = ALL_MASK_ATTENTION_FUNCTIONS[config._attn_implementation]
|
| 947 |
+
|
| 948 |
+
# Defaulting to using non-vmap based mask creations except when detecting
|
| 949 |
+
# users passing custom mask functions (as we cannot guarantee that they
|
| 950 |
+
# are properly index-based as required by our implementation).
|
| 951 |
+
use_vmap = False
|
| 952 |
+
|
| 953 |
+
# Do not allow skip if we are compiling (this is to match BC)
|
| 954 |
+
# TODO: cyril -> probably revisit and remove this, but a lot of tests rely on it
|
| 955 |
+
if _is_torch_xpu_available:
|
| 956 |
+
# Do not allow skip if we are compiling for decoding, but for prefill, we still allow skip to optimization the perf of 1st token generation
|
| 957 |
+
allow_is_causal_skip = not (getattr(past_key_values, "is_compileable", False) and q_length == 1)
|
| 958 |
+
else:
|
| 959 |
+
allow_is_causal_skip = not getattr(past_key_values, "is_compileable", False)
|
| 960 |
+
|
| 961 |
+
# Allow slight deviations from causal mask
|
| 962 |
+
# Note that it is very important to apply this before any other deviations of the mask (such as packed sequence mask,
|
| 963 |
+
# padding mask, etc) as the resulting mask may otherwise not be correct!
|
| 964 |
+
if or_mask_function is not None:
|
| 965 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 966 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 967 |
+
mask_factory_function = or_masks(mask_factory_function, or_mask_function)
|
| 968 |
+
allow_is_causal_skip = False
|
| 969 |
+
use_vmap = True
|
| 970 |
+
if and_mask_function is not None:
|
| 971 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 972 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 973 |
+
mask_factory_function = and_masks(mask_factory_function, and_mask_function)
|
| 974 |
+
allow_is_causal_skip = False
|
| 975 |
+
use_vmap = True
|
| 976 |
+
|
| 977 |
+
# If we detected packing format
|
| 978 |
+
if packed_sequence_mask is not None:
|
| 979 |
+
mask_factory_function = and_masks(mask_factory_function, packed_sequence_mask_function(packed_sequence_mask))
|
| 980 |
+
allow_is_causal_skip = False
|
| 981 |
+
|
| 982 |
+
# We now create the mask
|
| 983 |
+
causal_mask = mask_interface(
|
| 984 |
+
batch_size=batch_size,
|
| 985 |
+
q_length=q_length,
|
| 986 |
+
kv_length=kv_length,
|
| 987 |
+
q_offset=q_offset,
|
| 988 |
+
kv_offset=kv_offset,
|
| 989 |
+
mask_function=mask_factory_function,
|
| 990 |
+
attention_mask=attention_mask,
|
| 991 |
+
allow_is_causal_skip=allow_is_causal_skip, # additional kwarg for sdpa
|
| 992 |
+
dtype=dtype, # Additional kwarg for eager
|
| 993 |
+
config=config, # Pass the config as well, in case someone wants to easily have their own mask_interface
|
| 994 |
+
use_vmap=use_vmap, # Short-circuit to non-vmap expansions for the mask
|
| 995 |
+
device=device,
|
| 996 |
+
)
|
| 997 |
+
return causal_mask
|
| 998 |
+
|
| 999 |
+
|
| 1000 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 1001 |
+
def create_bidirectional_mask(
|
| 1002 |
+
config: PreTrainedConfig,
|
| 1003 |
+
inputs_embeds: torch.Tensor,
|
| 1004 |
+
attention_mask: torch.Tensor | None,
|
| 1005 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 1006 |
+
past_key_values: Cache | None = None,
|
| 1007 |
+
or_mask_function: Callable | None = None,
|
| 1008 |
+
and_mask_function: Callable | None = None,
|
| 1009 |
+
) -> torch.Tensor | BlockMask | None:
|
| 1010 |
+
"""
|
| 1011 |
+
Create a standard bidirectional mask based on the attention implementation used (stored in the config).
|
| 1012 |
+
|
| 1013 |
+
Args:
|
| 1014 |
+
config (`PreTrainedConfig`):
|
| 1015 |
+
The model config.
|
| 1016 |
+
inputs_embeds (`torch.Tensor`):
|
| 1017 |
+
The input embeddings of shape (batch_size, query_length, hidden_dim). This is only used to infer metadata
|
| 1018 |
+
such as the batch size, query length, dtype, and device.
|
| 1019 |
+
past_key_values (`Cache`, optional):
|
| 1020 |
+
The past key values, if we use a cache.
|
| 1021 |
+
attention_mask (`torch.Tensor`, optional):
|
| 1022 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, kv_length).
|
| 1023 |
+
It can also be an already prepared 4D mask of shape (batch_size, 1, query_length, kv_length),
|
| 1024 |
+
in which case it is returned as-is.
|
| 1025 |
+
encoder_hidden_states (`torch.Tensor`, optional):
|
| 1026 |
+
The input embeddings of shape (batch_size, kv_length, hidden_dim). If provided, it is used instead of
|
| 1027 |
+
`inputs_embeds` to infer the batch size, kv length and dtype.
|
| 1028 |
+
or_mask_function (`Callable`, optional):
|
| 1029 |
+
An optional mask function to combine with the base mask function (by doing the union of both). This is
|
| 1030 |
+
useful to easily overlay another mask on top, for example for image tokens handling.
|
| 1031 |
+
and_mask_function (`Callable`, optional):
|
| 1032 |
+
An optional mask function to combine with the base mask function (by doing the intersection of both). This is
|
| 1033 |
+
useful to easily overlay another mask on top, for example for image tokens handling.
|
| 1034 |
+
"""
|
| 1035 |
+
# We ignore a few irrelevant arguments at the end as we do not have a (growing) cache here
|
| 1036 |
+
early_exit, attention_mask, _, q_length, kv_length, q_offset, kv_offset = _preprocess_mask_arguments(
|
| 1037 |
+
config, inputs_embeds, attention_mask, past_key_values, None, 0, encoder_hidden_states
|
| 1038 |
+
)
|
| 1039 |
+
if early_exit:
|
| 1040 |
+
return attention_mask
|
| 1041 |
+
|
| 1042 |
+
embeds = encoder_hidden_states if encoder_hidden_states is not None else inputs_embeds
|
| 1043 |
+
batch_size, dtype, device = embeds.shape[0], embeds.dtype, embeds.device
|
| 1044 |
+
mask_factory_function = bidirectional_mask_function
|
| 1045 |
+
mask_interface = ALL_MASK_ATTENTION_FUNCTIONS[config._attn_implementation]
|
| 1046 |
+
|
| 1047 |
+
# Allow skipping the mask creation except we have additional masking operators (and/or masks)
|
| 1048 |
+
allow_is_bidirectional_skip = True
|
| 1049 |
+
# Defaulting to using non-vmap based mask creations except when detecting
|
| 1050 |
+
# users passing custom mask functions (as we cannot guarantee that they
|
| 1051 |
+
# are properly index-based as required by our implementation).
|
| 1052 |
+
use_vmap = False
|
| 1053 |
+
|
| 1054 |
+
# Allow slight deviations from the base mask
|
| 1055 |
+
# Note that it is very important to apply this before any other deviations of the mask (such as packed sequence mask,
|
| 1056 |
+
# padding mask, etc) as the resulting mask may otherwise not be correct!
|
| 1057 |
+
if or_mask_function is not None:
|
| 1058 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 1059 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 1060 |
+
mask_factory_function = or_masks(mask_factory_function, or_mask_function)
|
| 1061 |
+
allow_is_bidirectional_skip = False
|
| 1062 |
+
use_vmap = True
|
| 1063 |
+
if and_mask_function is not None:
|
| 1064 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 1065 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 1066 |
+
mask_factory_function = and_masks(mask_factory_function, and_mask_function)
|
| 1067 |
+
allow_is_bidirectional_skip = False
|
| 1068 |
+
use_vmap = True
|
| 1069 |
+
|
| 1070 |
+
# We now create the mask
|
| 1071 |
+
attention_mask = mask_interface(
|
| 1072 |
+
batch_size=batch_size,
|
| 1073 |
+
q_length=q_length,
|
| 1074 |
+
kv_length=kv_length,
|
| 1075 |
+
q_offset=q_offset,
|
| 1076 |
+
kv_offset=kv_offset,
|
| 1077 |
+
mask_function=mask_factory_function,
|
| 1078 |
+
attention_mask=attention_mask,
|
| 1079 |
+
# Additional kwargs for sdpa
|
| 1080 |
+
allow_is_causal_skip=False,
|
| 1081 |
+
allow_is_bidirectional_skip=allow_is_bidirectional_skip,
|
| 1082 |
+
dtype=dtype, # Additional kwarg for eager
|
| 1083 |
+
config=config, # Pass the config as well, in case someone wants to easily have their own mask_interface
|
| 1084 |
+
use_vmap=use_vmap, # Short-circuit to non-vmap expansions for the mask
|
| 1085 |
+
device=device,
|
| 1086 |
+
)
|
| 1087 |
+
return attention_mask
|
| 1088 |
+
|
| 1089 |
+
|
| 1090 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 1091 |
+
def create_sliding_window_causal_mask(
|
| 1092 |
+
config: PreTrainedConfig,
|
| 1093 |
+
inputs_embeds: torch.Tensor,
|
| 1094 |
+
attention_mask: torch.Tensor | None,
|
| 1095 |
+
cache_position: torch.Tensor | None = None, # not used anymore but kept for BC
|
| 1096 |
+
*,
|
| 1097 |
+
past_key_values: Cache | None,
|
| 1098 |
+
position_ids: torch.Tensor | None = None,
|
| 1099 |
+
or_mask_function: Callable | None = None,
|
| 1100 |
+
and_mask_function: Callable | None = None,
|
| 1101 |
+
) -> torch.Tensor | BlockMask | None:
|
| 1102 |
+
"""
|
| 1103 |
+
Create a sliding window causal mask based on the attention implementation used (stored in the config). This type
|
| 1104 |
+
of attention pattern was mostly democratized by Mistral. If `past_key_values` has an hybrid cache structure, this
|
| 1105 |
+
function will return the mask corresponding to one of the "sliding_attention" layers (to align to what is needed in the
|
| 1106 |
+
`modeling_xxx.py` files).
|
| 1107 |
+
|
| 1108 |
+
Args:
|
| 1109 |
+
config (`PreTrainedConfig`):
|
| 1110 |
+
The model config.
|
| 1111 |
+
inputs_embeds (`torch.Tensor`):
|
| 1112 |
+
The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
|
| 1113 |
+
batch size, query length and dtype.
|
| 1114 |
+
attention_mask (`torch.Tensor`, optional):
|
| 1115 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
|
| 1116 |
+
It can also be an already prepared 4D mask, in which case it is returned as-is.
|
| 1117 |
+
cache_position (`torch.Tensor`):
|
| 1118 |
+
Deprecated and unused.
|
| 1119 |
+
past_key_values (`Cache`, optional):
|
| 1120 |
+
The past key values, if we use a cache.
|
| 1121 |
+
position_ids (`torch.Tensor`, optional)
|
| 1122 |
+
A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
|
| 1123 |
+
or_mask_function (`Callable`, optional):
|
| 1124 |
+
An optional mask function to combine with the sliding causal mask function (by doing the union of both). This is
|
| 1125 |
+
useful to easily overlay another mask on top of the sliding causal one, for example for image tokens handling.
|
| 1126 |
+
and_mask_function (`Callable`, optional):
|
| 1127 |
+
An optional mask function to combine with the sliding causal mask function (by doing the intersection of both). This is
|
| 1128 |
+
useful to easily overlay another mask on top of the sliding causal one, for example for image tokens handling.
|
| 1129 |
+
"""
|
| 1130 |
+
# Power feature: if `is_causal` is False, then fallback to bi-directional mask for bi-directional attention
|
| 1131 |
+
# It allows to use decoder-only models with bi-directional attention as well
|
| 1132 |
+
if not getattr(config, "is_causal", True):
|
| 1133 |
+
return create_bidirectional_sliding_window_mask(
|
| 1134 |
+
config,
|
| 1135 |
+
inputs_embeds,
|
| 1136 |
+
attention_mask,
|
| 1137 |
+
past_key_values=past_key_values,
|
| 1138 |
+
or_mask_function=or_mask_function,
|
| 1139 |
+
and_mask_function=and_mask_function,
|
| 1140 |
+
)
|
| 1141 |
+
|
| 1142 |
+
# If we have an hybrid cache structure, here we want to create the mask for the sliding layers
|
| 1143 |
+
if hasattr(past_key_values, "is_sliding") and True in past_key_values.is_sliding:
|
| 1144 |
+
layer_idx = past_key_values.is_sliding.index(True)
|
| 1145 |
+
else:
|
| 1146 |
+
layer_idx = 0
|
| 1147 |
+
|
| 1148 |
+
early_exit, attention_mask, packed_sequence_mask, q_length, kv_length, q_offset, kv_offset = (
|
| 1149 |
+
_preprocess_mask_arguments(config, inputs_embeds, attention_mask, past_key_values, position_ids, layer_idx)
|
| 1150 |
+
)
|
| 1151 |
+
if early_exit:
|
| 1152 |
+
return attention_mask
|
| 1153 |
+
|
| 1154 |
+
sliding_window = getattr(config, "sliding_window", None)
|
| 1155 |
+
if sliding_window is None:
|
| 1156 |
+
raise ValueError("Could not find a `sliding_window` argument in the config, or it is not set")
|
| 1157 |
+
|
| 1158 |
+
batch_size, dtype, device = inputs_embeds.shape[0], inputs_embeds.dtype, inputs_embeds.device
|
| 1159 |
+
mask_factory_function = sliding_window_causal_mask_function(sliding_window)
|
| 1160 |
+
mask_interface = ALL_MASK_ATTENTION_FUNCTIONS[config._attn_implementation]
|
| 1161 |
+
|
| 1162 |
+
# Defaulting to using non-vmap based mask creations except when detecting
|
| 1163 |
+
# users passing custom mask functions (as we cannot guarantee that they
|
| 1164 |
+
# are properly index-based as required by our implementation).
|
| 1165 |
+
use_vmap = False
|
| 1166 |
+
# Do not allow skip if we are compiling (this is to match BC)
|
| 1167 |
+
# TODO: cyril -> probably revisit and remove this, but a lot of tests rely on it
|
| 1168 |
+
allow_is_causal_skip = not getattr(past_key_values, "is_compileable", False)
|
| 1169 |
+
|
| 1170 |
+
# Allow slight deviations from causal mask
|
| 1171 |
+
# Note that it is very important to apply this before any other deviations of the mask (such as packed sequence mask,
|
| 1172 |
+
# padding mask, etc) as the resulting mask may otherwise not be correct!
|
| 1173 |
+
if or_mask_function is not None:
|
| 1174 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 1175 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 1176 |
+
mask_factory_function = or_masks(mask_factory_function, or_mask_function)
|
| 1177 |
+
allow_is_causal_skip = False
|
| 1178 |
+
use_vmap = True
|
| 1179 |
+
if and_mask_function is not None:
|
| 1180 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 1181 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 1182 |
+
mask_factory_function = and_masks(mask_factory_function, and_mask_function)
|
| 1183 |
+
allow_is_causal_skip = False
|
| 1184 |
+
use_vmap = True
|
| 1185 |
+
|
| 1186 |
+
# If we detected packing format
|
| 1187 |
+
if packed_sequence_mask is not None:
|
| 1188 |
+
mask_factory_function = and_masks(mask_factory_function, packed_sequence_mask_function(packed_sequence_mask))
|
| 1189 |
+
allow_is_causal_skip = False
|
| 1190 |
+
|
| 1191 |
+
# We now create the mask
|
| 1192 |
+
causal_mask = mask_interface(
|
| 1193 |
+
batch_size=batch_size,
|
| 1194 |
+
q_length=q_length,
|
| 1195 |
+
kv_length=kv_length,
|
| 1196 |
+
q_offset=q_offset,
|
| 1197 |
+
kv_offset=kv_offset,
|
| 1198 |
+
mask_function=mask_factory_function,
|
| 1199 |
+
attention_mask=attention_mask,
|
| 1200 |
+
allow_is_causal_skip=allow_is_causal_skip, # additional kwarg for sdpa
|
| 1201 |
+
local_size=sliding_window, # Additional kwarg for sdpa
|
| 1202 |
+
dtype=dtype, # Additional kwarg for eager
|
| 1203 |
+
config=config, # Pass the config as well, in case someone wants to easily have their own mask_interface
|
| 1204 |
+
use_vmap=use_vmap, # Short-circuit to non-vmap expansions for the mask
|
| 1205 |
+
device=device,
|
| 1206 |
+
)
|
| 1207 |
+
return causal_mask
|
| 1208 |
+
|
| 1209 |
+
|
| 1210 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 1211 |
+
def create_bidirectional_sliding_window_mask(
|
| 1212 |
+
config: PreTrainedConfig,
|
| 1213 |
+
inputs_embeds: torch.Tensor,
|
| 1214 |
+
attention_mask: torch.Tensor | None,
|
| 1215 |
+
past_key_values: Cache | None = None,
|
| 1216 |
+
or_mask_function: Callable | None = None,
|
| 1217 |
+
and_mask_function: Callable | None = None,
|
| 1218 |
+
) -> torch.Tensor | BlockMask | None:
|
| 1219 |
+
"""
|
| 1220 |
+
Create a standard bidirectional sliding window mask based on the attention implementation used (stored in the config).
|
| 1221 |
+
|
| 1222 |
+
Args:
|
| 1223 |
+
config (`PreTrainedConfig`):
|
| 1224 |
+
The model config.
|
| 1225 |
+
inputs_embeds (`torch.Tensor`):
|
| 1226 |
+
The input embeddings of shape (batch_size, query_length, hidden_dim). This is only used to infer metadata
|
| 1227 |
+
such as the batch size, query length, dtype, and device.
|
| 1228 |
+
past_key_values (`Cache`, optional):
|
| 1229 |
+
The past key values, if we use a cache.
|
| 1230 |
+
attention_mask (`torch.Tensor`, optional):
|
| 1231 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, kv_length).
|
| 1232 |
+
It can also be an already prepared 4D mask of shape (batch_size, 1, query_length, kv_length),
|
| 1233 |
+
in which case it is returned as-is.
|
| 1234 |
+
or_mask_function (`Callable`, optional):
|
| 1235 |
+
An optional mask function to combine with the base mask function (by doing the union of both). This is
|
| 1236 |
+
useful to easily overlay another mask on top, for example for image tokens handling.
|
| 1237 |
+
and_mask_function (`Callable`, optional):
|
| 1238 |
+
An optional mask function to combine with the base mask function (by doing the intersection of both). This is
|
| 1239 |
+
useful to easily overlay another mask on top, for example for image tokens handling.
|
| 1240 |
+
"""
|
| 1241 |
+
# We ignore a few irrelevant arguments at the end as we do not have a (growing) cache here
|
| 1242 |
+
early_exit, attention_mask, _, q_length, kv_length, q_offset, kv_offset = _preprocess_mask_arguments(
|
| 1243 |
+
config, inputs_embeds, attention_mask, past_key_values, None, 0
|
| 1244 |
+
)
|
| 1245 |
+
if early_exit:
|
| 1246 |
+
return attention_mask
|
| 1247 |
+
|
| 1248 |
+
sliding_window = getattr(config, "sliding_window", None)
|
| 1249 |
+
if sliding_window is None:
|
| 1250 |
+
raise ValueError("Could not find a `sliding_window` argument in the config, or it is not set")
|
| 1251 |
+
|
| 1252 |
+
batch_size, dtype, device = inputs_embeds.shape[0], inputs_embeds.dtype, inputs_embeds.device
|
| 1253 |
+
mask_factory_function = sliding_window_bidirectional_mask_function(sliding_window)
|
| 1254 |
+
mask_interface = ALL_MASK_ATTENTION_FUNCTIONS[config._attn_implementation]
|
| 1255 |
+
|
| 1256 |
+
use_vmap = False
|
| 1257 |
+
allow_is_bidirectional_skip = True
|
| 1258 |
+
|
| 1259 |
+
if or_mask_function is not None:
|
| 1260 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 1261 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 1262 |
+
mask_factory_function = or_masks(mask_factory_function, or_mask_function)
|
| 1263 |
+
allow_is_bidirectional_skip = False
|
| 1264 |
+
use_vmap = True
|
| 1265 |
+
if and_mask_function is not None:
|
| 1266 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 1267 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 1268 |
+
mask_factory_function = and_masks(mask_factory_function, and_mask_function)
|
| 1269 |
+
allow_is_bidirectional_skip = False
|
| 1270 |
+
use_vmap = True
|
| 1271 |
+
|
| 1272 |
+
attention_mask = mask_interface(
|
| 1273 |
+
batch_size=batch_size,
|
| 1274 |
+
q_length=q_length,
|
| 1275 |
+
kv_length=kv_length,
|
| 1276 |
+
q_offset=q_offset,
|
| 1277 |
+
kv_offset=kv_offset,
|
| 1278 |
+
mask_function=mask_factory_function,
|
| 1279 |
+
attention_mask=attention_mask,
|
| 1280 |
+
allow_is_causal_skip=False,
|
| 1281 |
+
allow_is_bidirectional_skip=allow_is_bidirectional_skip,
|
| 1282 |
+
local_size=sliding_window, # Additional kwarg for sdpa
|
| 1283 |
+
dtype=dtype, # Additional kwarg for eager
|
| 1284 |
+
config=config, # Pass the config as well, in case someone wants to easily have their own mask_interface
|
| 1285 |
+
use_vmap=use_vmap, # Short-circuit to non-vmap expansions for the mask
|
| 1286 |
+
device=device,
|
| 1287 |
+
)
|
| 1288 |
+
return attention_mask
|
| 1289 |
+
|
| 1290 |
+
|
| 1291 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 1292 |
+
def create_chunked_causal_mask(
|
| 1293 |
+
config: PreTrainedConfig,
|
| 1294 |
+
inputs_embeds: torch.Tensor,
|
| 1295 |
+
attention_mask: torch.Tensor | None,
|
| 1296 |
+
cache_position: torch.Tensor | None = None, # not used anymore but kept for BC
|
| 1297 |
+
*,
|
| 1298 |
+
past_key_values: Cache | None,
|
| 1299 |
+
position_ids: torch.Tensor | None = None,
|
| 1300 |
+
or_mask_function: Callable | None = None,
|
| 1301 |
+
and_mask_function: Callable | None = None,
|
| 1302 |
+
) -> torch.Tensor | BlockMask | None:
|
| 1303 |
+
"""
|
| 1304 |
+
Create a chunked attention causal mask based on the attention implementation used (stored in the config). This type
|
| 1305 |
+
of attention pattern was mostly democratized by Llama4. If `past_key_values` has an hybrid cache structure, this
|
| 1306 |
+
function will return the mask corresponding to one of the "chunked_attention" layers (to align to what is needed in the
|
| 1307 |
+
`modeling_xxx.py` files).
|
| 1308 |
+
|
| 1309 |
+
Args:
|
| 1310 |
+
config (`PreTrainedConfig`):
|
| 1311 |
+
The model config.
|
| 1312 |
+
inputs_embeds (`torch.Tensor`):
|
| 1313 |
+
The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
|
| 1314 |
+
batch size, query length and dtype.
|
| 1315 |
+
attention_mask (`torch.Tensor`, optional):
|
| 1316 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
|
| 1317 |
+
It can also be an already prepared 4D mask, in which case it is returned as-is.
|
| 1318 |
+
cache_position (`torch.Tensor`):
|
| 1319 |
+
Deprecated and unused.
|
| 1320 |
+
past_key_values (`Cache`, optional):
|
| 1321 |
+
The past key values, if we use a cache.
|
| 1322 |
+
position_ids (`torch.Tensor`, optional)
|
| 1323 |
+
A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
|
| 1324 |
+
or_mask_function (`Callable`, optional):
|
| 1325 |
+
An optional mask function to combine with the chunked causal mask function (by doing the union of both). This is
|
| 1326 |
+
useful to easily overlay another mask on top of the chunked causal one, for example for image tokens handling.
|
| 1327 |
+
and_mask_function (`Callable`, optional):
|
| 1328 |
+
An optional mask function to combine with the chunked causal mask function (by doing the intersection of both). This is
|
| 1329 |
+
useful to easily overlay another mask on top of the chunked causal one, for example for image tokens handling.
|
| 1330 |
+
"""
|
| 1331 |
+
# If we have an hybrid cache structure, here we want to create the mask for the sliding layers
|
| 1332 |
+
if hasattr(past_key_values, "is_sliding") and True in past_key_values.is_sliding:
|
| 1333 |
+
layer_idx = past_key_values.is_sliding.index(True)
|
| 1334 |
+
else:
|
| 1335 |
+
layer_idx = 0
|
| 1336 |
+
|
| 1337 |
+
early_exit, attention_mask, packed_sequence_mask, q_length, kv_length, q_offset, kv_offset = (
|
| 1338 |
+
_preprocess_mask_arguments(config, inputs_embeds, attention_mask, past_key_values, position_ids, layer_idx)
|
| 1339 |
+
)
|
| 1340 |
+
if early_exit:
|
| 1341 |
+
return attention_mask
|
| 1342 |
+
|
| 1343 |
+
chunk_size = getattr(config, "attention_chunk_size", None)
|
| 1344 |
+
if chunk_size is None:
|
| 1345 |
+
raise ValueError("Could not find an `attention_chunk_size` argument in the config, or it is not set")
|
| 1346 |
+
|
| 1347 |
+
# Raise if using chunked attention on context too large with FA
|
| 1348 |
+
if is_flash_attention_requested(config) and kv_length + kv_offset > chunk_size:
|
| 1349 |
+
raise ValueError(
|
| 1350 |
+
"Flash attention cannot handle chunked attention, and the key-value length is larger than the chunk size so the "
|
| 1351 |
+
"chunked pattern cannot be respected. You should use another `attn_implementation` when instantiating the model"
|
| 1352 |
+
)
|
| 1353 |
+
|
| 1354 |
+
batch_size, dtype, device = inputs_embeds.shape[0], inputs_embeds.dtype, inputs_embeds.device
|
| 1355 |
+
# For chunked attention and batched inputs, we need to take the number of left padding tokens into account
|
| 1356 |
+
# to start the chunk from the actual start of the sequence for the padded sequence
|
| 1357 |
+
if attention_mask is not None:
|
| 1358 |
+
# Only count the left padding tokens, not all of them
|
| 1359 |
+
left_padding_tokens = (attention_mask.cumsum(dim=-1) == torch.zeros_like(attention_mask)).sum(dim=-1)
|
| 1360 |
+
else:
|
| 1361 |
+
left_padding_tokens = torch.zeros(batch_size, device=device, dtype=int)
|
| 1362 |
+
mask_factory_function = chunked_causal_mask_function(chunk_size, left_padding_tokens)
|
| 1363 |
+
mask_interface = ALL_MASK_ATTENTION_FUNCTIONS[config._attn_implementation]
|
| 1364 |
+
|
| 1365 |
+
# Defaulting to using non-vmap based mask creations except when detecting
|
| 1366 |
+
# users passing custom mask functions (as we cannot guarantee that they
|
| 1367 |
+
# are properly index-based as required by our implementation).
|
| 1368 |
+
use_vmap = False
|
| 1369 |
+
# Do not allow skip if we are compiling (this is to match BC)
|
| 1370 |
+
# TODO: cyril -> probably revisit and remove this, but a lot of tests rely on it
|
| 1371 |
+
allow_is_causal_skip = not getattr(past_key_values, "is_compileable", False)
|
| 1372 |
+
|
| 1373 |
+
# Allow slight deviations from causal mask
|
| 1374 |
+
# Note that it is very important to apply this before any other deviations of the mask (such as packed sequence mask,
|
| 1375 |
+
# padding mask, etc) as the resulting mask may otherwise not be correct!
|
| 1376 |
+
if or_mask_function is not None:
|
| 1377 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 1378 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 1379 |
+
mask_factory_function = or_masks(mask_factory_function, or_mask_function)
|
| 1380 |
+
allow_is_causal_skip = False
|
| 1381 |
+
use_vmap = True
|
| 1382 |
+
if and_mask_function is not None:
|
| 1383 |
+
if not _is_torch_greater_or_equal_than_2_6:
|
| 1384 |
+
raise ValueError("Using `or_mask_function` or `and_mask_function` arguments require torch>=2.6")
|
| 1385 |
+
mask_factory_function = and_masks(mask_factory_function, and_mask_function)
|
| 1386 |
+
allow_is_causal_skip = False
|
| 1387 |
+
use_vmap = True
|
| 1388 |
+
|
| 1389 |
+
# If we detected packing format
|
| 1390 |
+
if packed_sequence_mask is not None:
|
| 1391 |
+
mask_factory_function = and_masks(mask_factory_function, packed_sequence_mask_function(packed_sequence_mask))
|
| 1392 |
+
allow_is_causal_skip = False
|
| 1393 |
+
|
| 1394 |
+
# We now create the mask
|
| 1395 |
+
causal_mask = mask_interface(
|
| 1396 |
+
batch_size=batch_size,
|
| 1397 |
+
q_length=q_length,
|
| 1398 |
+
kv_length=kv_length,
|
| 1399 |
+
q_offset=q_offset,
|
| 1400 |
+
kv_offset=kv_offset,
|
| 1401 |
+
mask_function=mask_factory_function,
|
| 1402 |
+
attention_mask=attention_mask,
|
| 1403 |
+
allow_is_causal_skip=allow_is_causal_skip, # additional kwarg for sdpa
|
| 1404 |
+
local_size=chunk_size, # Additional kwarg for sdpa
|
| 1405 |
+
dtype=dtype, # Additional kwarg for eager
|
| 1406 |
+
config=config, # Pass the config as well, in case someone wants to easily have their own mask_interface
|
| 1407 |
+
use_vmap=use_vmap, # Short-circuit to non-vmap expansions for the mask
|
| 1408 |
+
device=device,
|
| 1409 |
+
)
|
| 1410 |
+
return causal_mask
|
| 1411 |
+
|
| 1412 |
+
|
| 1413 |
+
LAYER_PATTERN_TO_MASK_FUNCTION_MAPPING = {
|
| 1414 |
+
"full_attention": create_causal_mask,
|
| 1415 |
+
"sliding_attention": create_sliding_window_causal_mask,
|
| 1416 |
+
"chunked_attention": create_chunked_causal_mask,
|
| 1417 |
+
}
|
| 1418 |
+
|
| 1419 |
+
|
| 1420 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 1421 |
+
def create_masks_for_generate(
|
| 1422 |
+
config: PreTrainedConfig,
|
| 1423 |
+
inputs_embeds: torch.Tensor,
|
| 1424 |
+
attention_mask: torch.Tensor | None,
|
| 1425 |
+
past_key_values: Cache | None,
|
| 1426 |
+
position_ids: torch.Tensor | None = None,
|
| 1427 |
+
or_mask_function: Callable | None = None,
|
| 1428 |
+
and_mask_function: Callable | None = None,
|
| 1429 |
+
**kwargs,
|
| 1430 |
+
):
|
| 1431 |
+
"""
|
| 1432 |
+
This function mimics how we create the masks in the `modeling_xxx.py` files, and is used in places like `generate`
|
| 1433 |
+
in order to easily create the masks in advance, when we compile the forwards with Static caches.
|
| 1434 |
+
|
| 1435 |
+
Args:
|
| 1436 |
+
config (`PreTrainedConfig`):
|
| 1437 |
+
The model config.
|
| 1438 |
+
inputs_embeds (`torch.Tensor`):
|
| 1439 |
+
The input embeddings of shape (batch_size, query_length, hidden_dim). This is used only to infer the
|
| 1440 |
+
batch size, query length and dtype.
|
| 1441 |
+
attention_mask (`torch.Tensor`, optional):
|
| 1442 |
+
The 2D attention mask corresponding to padded tokens of shape (batch_size, number_of_seen_tokens+q_length).
|
| 1443 |
+
It can also be an already prepared 4D mask, in which case it is returned as-is.
|
| 1444 |
+
past_key_values (`Cache`, optional):
|
| 1445 |
+
The past key values, if we use a cache.
|
| 1446 |
+
position_ids (`torch.Tensor`, optional)
|
| 1447 |
+
A 2D tensor of shape (batch_size, query_length) indicating the positions of each token in the sequences.
|
| 1448 |
+
or_mask_function (`Callable`, optional):
|
| 1449 |
+
An optional mask function to combine with the other mask function (by doing the union of both). This is
|
| 1450 |
+
useful to easily overlay another mask on top of the causal one, for example for image tokens handling.
|
| 1451 |
+
and_mask_function (`Callable`, optional):
|
| 1452 |
+
An optional mask function to combine with the other mask function (by doing the intersection of both). This is
|
| 1453 |
+
useful to easily overlay another mask on top of the causal one, for example for image tokens handling.
|
| 1454 |
+
"""
|
| 1455 |
+
# The attribute reside in the text config for composite models
|
| 1456 |
+
effective_config = config.get_text_config()
|
| 1457 |
+
# Prepare the mask args
|
| 1458 |
+
mask_kwargs = {
|
| 1459 |
+
"config": effective_config,
|
| 1460 |
+
"inputs_embeds": inputs_embeds,
|
| 1461 |
+
"attention_mask": attention_mask,
|
| 1462 |
+
"past_key_values": past_key_values,
|
| 1463 |
+
"position_ids": position_ids,
|
| 1464 |
+
"or_mask_function": or_mask_function,
|
| 1465 |
+
"and_mask_function": and_mask_function,
|
| 1466 |
+
}
|
| 1467 |
+
|
| 1468 |
+
# If the attribute exist, we need several masks
|
| 1469 |
+
if hasattr(effective_config, "layer_types"):
|
| 1470 |
+
causal_masks = {}
|
| 1471 |
+
for layer_pattern in set(effective_config.layer_types):
|
| 1472 |
+
causal_masks[layer_pattern] = LAYER_PATTERN_TO_MASK_FUNCTION_MAPPING[layer_pattern](**mask_kwargs)
|
| 1473 |
+
return causal_masks
|
| 1474 |
+
# In this case, all layers are sliding
|
| 1475 |
+
elif getattr(effective_config, "sliding_window", None) is not None:
|
| 1476 |
+
return create_sliding_window_causal_mask(**mask_kwargs)
|
| 1477 |
+
# In this case, all layers are chunked
|
| 1478 |
+
elif getattr(effective_config, "attention_chunk_size", None) is not None:
|
| 1479 |
+
return create_chunked_causal_mask(**mask_kwargs)
|
| 1480 |
+
# All layers use standard causal attention
|
| 1481 |
+
return create_causal_mask(**mask_kwargs)
|
| 1482 |
+
|
| 1483 |
+
|
| 1484 |
+
# Below are utilities to pretty-print the different masks
|
| 1485 |
+
# Print the matrix with words as row labels
|
| 1486 |
+
GREEN = "\033[92m"
|
| 1487 |
+
YELLOW = "\033[93m"
|
| 1488 |
+
RESET = "\033[0m"
|
| 1489 |
+
BLACK_SQUARE = "■"
|
| 1490 |
+
WHITE_SQUARE = "⬚"
|
| 1491 |
+
GREY_SQUARE = "∙"
|
| 1492 |
+
LOW_TRIANGLE = "⬕"
|
| 1493 |
+
UPPER_TRIANGLE = "⬔"
|
| 1494 |
+
|
| 1495 |
+
|
| 1496 |
+
def get_style(style):
|
| 1497 |
+
if style == "majong":
|
| 1498 |
+
BLACK_SQUARE = "🀞" # Full block (represents "on" or active)
|
| 1499 |
+
BLACK_SQUARE = "🀙" # Full block (represents "on" or active)
|
| 1500 |
+
WHITE_SQUARE = "🀆" # "▒" # Light shade (represents "off" or inactive)
|
| 1501 |
+
LOW_TRIANGLE = "🀛" # Lower left triangle (stylized indication)
|
| 1502 |
+
UPPER_TRIANGLE = "🀛" # Upper left triangle (stylized indication)
|
| 1503 |
+
else:
|
| 1504 |
+
BLACK_SQUARE = "█" # Full block (represents "on" or active)
|
| 1505 |
+
WHITE_SQUARE = "░" # "▒" # Light shade (represents "off" or inactive)
|
| 1506 |
+
LOW_TRIANGLE = "▙" # Lower left triangle (stylized indication))
|
| 1507 |
+
UPPER_TRIANGLE = "▜" # Upper left triangle (stylized indication)
|
| 1508 |
+
|
| 1509 |
+
return BLACK_SQUARE, WHITE_SQUARE, LOW_TRIANGLE, UPPER_TRIANGLE
|
| 1510 |
+
|
| 1511 |
+
|
| 1512 |
+
# LOW_TRIANGLE = UPPER_TRIANGLE = "⟍" # Upper right triangle (stylized indication)
|
| 1513 |
+
|
| 1514 |
+
YELLOW_SQUARE = f"{YELLOW}{BLACK_SQUARE}{RESET}"
|
| 1515 |
+
GREEN_SQUARE = f"{GREEN}{BLACK_SQUARE}{RESET}"
|
| 1516 |
+
|
| 1517 |
+
|
| 1518 |
+
def tensor_to_mask_visual(original_tensor: torch.Tensor, grid_size=(20, 40), style="majong") -> str:
|
| 1519 |
+
BLACK_SQUARE, WHITE_SQUARE, LOW_TRIANGLE, UPPER_TRIANGLE = get_style(style)
|
| 1520 |
+
h, w = original_tensor.shape
|
| 1521 |
+
max_h, max_w = grid_size
|
| 1522 |
+
if not (h < max_h and w < max_w):
|
| 1523 |
+
# Preserve aspect ratio within max grid size
|
| 1524 |
+
aspect_ratio = 2 * w / h
|
| 1525 |
+
if aspect_ratio > 1:
|
| 1526 |
+
w = max_w
|
| 1527 |
+
h = min(max_h, max(1, round(max_w / aspect_ratio)))
|
| 1528 |
+
else:
|
| 1529 |
+
h = max_h
|
| 1530 |
+
w = max(1, round(max_h * aspect_ratio))
|
| 1531 |
+
|
| 1532 |
+
# Step 1: Rescale tensor by average pooling
|
| 1533 |
+
tensor = original_tensor.unsqueeze(0).unsqueeze(0) # Add batch and channel dimensions
|
| 1534 |
+
tensor = F.adaptive_avg_pool2d(tensor, output_size=(h, w))[0, 0] # Remove extra dims
|
| 1535 |
+
else:
|
| 1536 |
+
tensor = original_tensor
|
| 1537 |
+
|
| 1538 |
+
# Step 3: Build the string representation
|
| 1539 |
+
result = []
|
| 1540 |
+
for i in range(h):
|
| 1541 |
+
row = ""
|
| 1542 |
+
for j in range(w):
|
| 1543 |
+
if tensor[i, j] == 1:
|
| 1544 |
+
row += BLACK_SQUARE
|
| 1545 |
+
elif tensor[i, j] == 0:
|
| 1546 |
+
row += WHITE_SQUARE
|
| 1547 |
+
else:
|
| 1548 |
+
if j > 0:
|
| 1549 |
+
if tensor[i, j - 1] == 1:
|
| 1550 |
+
row += LOW_TRIANGLE
|
| 1551 |
+
elif tensor[i, j - 1] == 0:
|
| 1552 |
+
row += UPPER_TRIANGLE
|
| 1553 |
+
else:
|
| 1554 |
+
row += BLACK_SQUARE if tensor[i, j] == 1 else WHITE_SQUARE
|
| 1555 |
+
else:
|
| 1556 |
+
row += (
|
| 1557 |
+
BLACK_SQUARE
|
| 1558 |
+
if tensor[i, j] == 1
|
| 1559 |
+
else (
|
| 1560 |
+
WHITE_SQUARE
|
| 1561 |
+
if tensor[i, j] == 0
|
| 1562 |
+
else (UPPER_TRIANGLE if tensor[i, j + 1] == 1 else LOW_TRIANGLE)
|
| 1563 |
+
)
|
| 1564 |
+
)
|
| 1565 |
+
result.append(row)
|
| 1566 |
+
|
| 1567 |
+
return "\n".join(result)
|
| 1568 |
+
|
| 1569 |
+
|
| 1570 |
+
class AttentionMask(torch.Tensor):
|
| 1571 |
+
def __new__(cls, data, style=None):
|
| 1572 |
+
# Create a new instance of AttentionMask as a Tensor
|
| 1573 |
+
cls.style = style
|
| 1574 |
+
return torch.Tensor._make_subclass(cls, data, require_grad=False)
|
| 1575 |
+
|
| 1576 |
+
def __init__(self, data):
|
| 1577 |
+
# You can initialize any additional metadata here if needed
|
| 1578 |
+
pass
|
| 1579 |
+
|
| 1580 |
+
def to_string(self, grid_size=(20, 40), limit=4):
|
| 1581 |
+
"""Returns a string representation of the block mask."""
|
| 1582 |
+
dense_mask = self
|
| 1583 |
+
*batch_dims, num_rows, num_cols = dense_mask.shape
|
| 1584 |
+
total_vis = []
|
| 1585 |
+
|
| 1586 |
+
for idx, batch_idx in enumerate(itertools.product(*[range(i) for i in batch_dims])):
|
| 1587 |
+
if idx == limit:
|
| 1588 |
+
total_vis.append("...")
|
| 1589 |
+
total_vis.append("To print out more, set AttentionMask.to_string(limit=N)")
|
| 1590 |
+
total_vis.append("You can also index (AttentionMask[batch, head]) to choose a specific batch or head")
|
| 1591 |
+
break
|
| 1592 |
+
block_vis = tensor_to_mask_visual(dense_mask[batch_idx], grid_size=grid_size, style=self.style)
|
| 1593 |
+
total_vis.append(block_vis)
|
| 1594 |
+
|
| 1595 |
+
total_vis.append(f"torch.Tensor(shape={tuple(self.shape)}, dtype={self.dtype})")
|
| 1596 |
+
return "\n".join(total_vis)
|
| 1597 |
+
|
| 1598 |
+
def __repr__(self):
|
| 1599 |
+
return self.to_string()
|
| 1600 |
+
|
| 1601 |
+
def __str__(self):
|
| 1602 |
+
return self.to_string()
|
| 1603 |
+
|
| 1604 |
+
@classmethod
|
| 1605 |
+
def from_tensor(cls, tensor: torch.Tensor, style: str | None = None) -> "AttentionMask":
|
| 1606 |
+
res = cls(tensor)
|
| 1607 |
+
res.style = style
|
| 1608 |
+
return res
|
third_party/transformers/src/transformers/model_debugging_utils.py
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Inc. team.
|
| 2 |
+
# 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 |
+
import functools
|
| 17 |
+
import json
|
| 18 |
+
import os
|
| 19 |
+
import re
|
| 20 |
+
from contextlib import contextmanager, redirect_stdout
|
| 21 |
+
from io import StringIO
|
| 22 |
+
|
| 23 |
+
from .utils import logging
|
| 24 |
+
from .utils.import_utils import is_torch_available, requires
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
if is_torch_available():
|
| 28 |
+
import torch
|
| 29 |
+
from safetensors.torch import save_file
|
| 30 |
+
|
| 31 |
+
_torch_distributed_available = False
|
| 32 |
+
# Note to code inspectors: this toolbox is intended for people who add models to `transformers`.
|
| 33 |
+
if torch.distributed.is_available():
|
| 34 |
+
import torch.distributed.tensor
|
| 35 |
+
|
| 36 |
+
_torch_distributed_available = True
|
| 37 |
+
else:
|
| 38 |
+
_torch_distributed_available = False
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
logger = logging.get_logger(__name__)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def _is_rank_zero():
|
| 45 |
+
"""Return True if rank=0 or we aren't running distributed."""
|
| 46 |
+
if not (_torch_distributed_available and torch.distributed.is_initialized()):
|
| 47 |
+
return True
|
| 48 |
+
return torch.distributed.get_rank() == 0
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
MEMORY_ADDRESS_REGEX = re.compile(r"object at 0x[0-9A-Fa-f]+")
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def _sanitize_repr_for_diff(x_str: str) -> str:
|
| 55 |
+
"""
|
| 56 |
+
Replace memory addresses in an object's repr with a stable placeholder
|
| 57 |
+
so that beautiful JSON diffs won't be ruined by ephemeral addresses.
|
| 58 |
+
"""
|
| 59 |
+
return MEMORY_ADDRESS_REGEX.sub("object at 0xXXXXXXXX", x_str)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def _dtensor_repr(x):
|
| 63 |
+
"""Return a stable string representation for a DTensor-like object."""
|
| 64 |
+
if _is_rank_zero():
|
| 65 |
+
return f"DTensor (rank0) -> {repr(x._local_tensor)}"
|
| 66 |
+
return "DTensor(non-rank0)"
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def _serialize_tensor_like_io(
|
| 70 |
+
value, debug_path: str | None = None, use_repr: bool = True, path_to_value: str | None = None
|
| 71 |
+
):
|
| 72 |
+
"""
|
| 73 |
+
Converts Tensors and DTensors to a JSON-serializable dictionary representation.
|
| 74 |
+
|
| 75 |
+
Args:
|
| 76 |
+
value: Any Python object, often including torch Tensors, lists, dicts, etc.
|
| 77 |
+
debug_path (`str`, *optional*, defaults to `None`): Directory to dump debug JSON and SafeTensors files.
|
| 78 |
+
use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensor as the
|
| 79 |
+
`value` property in the asscoiated FULL_TENSORS.json file, or to store the full tensors in separate
|
| 80 |
+
SafeTensors file and store the relative path to that file in the `value` property in the dictionary.
|
| 81 |
+
path_to_value (`str`, *optional*, defaults to `None`): The file name for the SafeTensors file holding the full
|
| 82 |
+
tensor value if `use_repr=False`.
|
| 83 |
+
|
| 84 |
+
Returns:
|
| 85 |
+
A nested Python structure (list, dict, or sanitized string) that is safe to json.dump.
|
| 86 |
+
"""
|
| 87 |
+
torch.set_printoptions(sci_mode=True)
|
| 88 |
+
|
| 89 |
+
if use_repr:
|
| 90 |
+
value_out = _repr_to_list(value)
|
| 91 |
+
elif path_to_value:
|
| 92 |
+
if not path_to_value.endswith(".safetensors"):
|
| 93 |
+
path_to_value += ".safetensors"
|
| 94 |
+
|
| 95 |
+
filepath = os.path.join(debug_path, path_to_value) if debug_path else path_to_value
|
| 96 |
+
save_file({"data": value.contiguous().detach().cpu()}, filepath)
|
| 97 |
+
value_out = f"./{path_to_value}"
|
| 98 |
+
else:
|
| 99 |
+
raise ValueError(f"{use_repr=} and {path_to_value=} cannot both be falsy.")
|
| 100 |
+
|
| 101 |
+
out = {
|
| 102 |
+
"shape": repr(value.shape),
|
| 103 |
+
"dtype": repr(value.dtype),
|
| 104 |
+
"value": value_out,
|
| 105 |
+
}
|
| 106 |
+
if value.dtype in {torch.float16, torch.float32, torch.bfloat16}:
|
| 107 |
+
out.update(
|
| 108 |
+
{
|
| 109 |
+
"mean": _sanitize_repr_for_diff(repr(value.mean())),
|
| 110 |
+
"std": _sanitize_repr_for_diff(repr(value.std())),
|
| 111 |
+
"min": _sanitize_repr_for_diff(repr(value.min())),
|
| 112 |
+
"max": _sanitize_repr_for_diff(repr(value.max())),
|
| 113 |
+
}
|
| 114 |
+
)
|
| 115 |
+
return out
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def _serialize_io(value, debug_path: str | None = None, use_repr: bool = True, path_to_value: str | None = None):
|
| 119 |
+
"""
|
| 120 |
+
Recursively build a JSON-serializable Python structure from `value`.
|
| 121 |
+
Tensors and DTensors become either sanitized repr strings, or are saved to disk as SafeTensors files and their
|
| 122 |
+
relative paths are recorded in the returned Python structure.
|
| 123 |
+
Lists/tuples/dicts are recursed into.
|
| 124 |
+
All memory addresses are replaced with a stable placeholder.
|
| 125 |
+
|
| 126 |
+
Args:
|
| 127 |
+
value: Any Python object, often including torch Tensors, lists, dicts, etc.
|
| 128 |
+
debug_path (`str`, *optional*, defaults to `None`): Directory to dump debug JSON and SafeTensors files.
|
| 129 |
+
use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensors as the
|
| 130 |
+
`value` property in the asscoiated FULL_TENSORS.json file, or to store full tensors in separate SafeTensors
|
| 131 |
+
files and store the relative path to that file in the `value` property.
|
| 132 |
+
path_to_value (`str`, *optional*, defaults to `None`): The file name for the SafeTensors file holding the full
|
| 133 |
+
tensor value if `use_repr=False`.
|
| 134 |
+
|
| 135 |
+
Returns:
|
| 136 |
+
A nested Python structure (list, dict, or sanitized string) that is safe to json.dump.
|
| 137 |
+
"""
|
| 138 |
+
if isinstance(value, (list, tuple)):
|
| 139 |
+
return [
|
| 140 |
+
_serialize_io(v, debug_path=debug_path, use_repr=use_repr, path_to_value=f"{path_to_value}_{i}")
|
| 141 |
+
for i, v in enumerate(value)
|
| 142 |
+
]
|
| 143 |
+
|
| 144 |
+
if isinstance(value, dict):
|
| 145 |
+
return {
|
| 146 |
+
k: _serialize_io(v, debug_path=debug_path, use_repr=use_repr, path_to_value=f"{path_to_value}_{k}")
|
| 147 |
+
for k, v in value.items()
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
if hasattr(value, "_local_tensor"):
|
| 151 |
+
return _serialize_tensor_like_io(
|
| 152 |
+
value._local_tensor, debug_path=debug_path, use_repr=use_repr, path_to_value=path_to_value
|
| 153 |
+
)
|
| 154 |
+
|
| 155 |
+
if isinstance(value, torch.Tensor):
|
| 156 |
+
return _serialize_tensor_like_io(value, debug_path=debug_path, use_repr=use_repr, path_to_value=path_to_value)
|
| 157 |
+
|
| 158 |
+
return _sanitize_repr_for_diff(repr(value))
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def _repr_to_list(value: torch.Tensor):
|
| 162 |
+
"""
|
| 163 |
+
Converts a tensor into a sanitized multi-line string representation.
|
| 164 |
+
|
| 165 |
+
Args:
|
| 166 |
+
value (`torch.Tensor`): The tensor to represent.
|
| 167 |
+
|
| 168 |
+
Returns:
|
| 169 |
+
`list[str]`: List of string lines representing the tensor.
|
| 170 |
+
"""
|
| 171 |
+
torch.set_printoptions(sci_mode=True, linewidth=120)
|
| 172 |
+
with StringIO() as buf, redirect_stdout(buf):
|
| 173 |
+
print(value) # to redirected stdout to avoid line splits
|
| 174 |
+
raw = buf.getvalue()
|
| 175 |
+
return _sanitize_repr_for_diff(raw).splitlines()
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
def prune_outputs_if_children(node):
|
| 179 |
+
# if there are children, remove this node's "outputs"
|
| 180 |
+
# so we only see outputs at the leaf level
|
| 181 |
+
if node.get("children"):
|
| 182 |
+
node.pop("outputs", None)
|
| 183 |
+
for child in node["children"]:
|
| 184 |
+
prune_outputs_if_children(child)
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
LAYER_SUFFIX_RE = re.compile(r"(.*)\.(\d+)$") # should be generic enough, ends with a number
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
def is_layer_block(node):
|
| 191 |
+
"""
|
| 192 |
+
Checks whether a node represents a layer block with submodules.
|
| 193 |
+
|
| 194 |
+
Args:
|
| 195 |
+
node (`dict`): A node from the call tree.
|
| 196 |
+
|
| 197 |
+
Returns:
|
| 198 |
+
`bool`: Whether the node is a layer block.
|
| 199 |
+
"""
|
| 200 |
+
match = LAYER_SUFFIX_RE.match(node.get("module_path", ""))
|
| 201 |
+
if not match or not node.get("children"):
|
| 202 |
+
return False
|
| 203 |
+
number = match.group(2)
|
| 204 |
+
return any(f".{number}." in child.get("module_path", "") for child in node["children"])
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
def prune_intermediate_layers(node):
|
| 208 |
+
"""
|
| 209 |
+
Recursively removes intermediate layers from the tree to improve readability.
|
| 210 |
+
Keeps at least the first and last layers if many consecutive layers are present.
|
| 211 |
+
|
| 212 |
+
Args:
|
| 213 |
+
node (`dict`): The root or subnode to prune recursively.
|
| 214 |
+
"""
|
| 215 |
+
if not node.get("children"):
|
| 216 |
+
return
|
| 217 |
+
layer_blocks = [(i, child) for i, child in enumerate(node["children"]) if is_layer_block(child)]
|
| 218 |
+
|
| 219 |
+
if len(layer_blocks) > 2:
|
| 220 |
+
to_remove = [i for i, _ in layer_blocks[1:-1]]
|
| 221 |
+
node["children"] = [child for i, child in enumerate(node["children"]) if i not in to_remove]
|
| 222 |
+
|
| 223 |
+
for child in node["children"]:
|
| 224 |
+
prune_intermediate_layers(child)
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def log_model_debug_trace(debug_path: str | None, model):
|
| 228 |
+
if debug_path:
|
| 229 |
+
try:
|
| 230 |
+
os.makedirs(debug_path, exist_ok=True)
|
| 231 |
+
base = os.path.join(debug_path, model._debugger_module_dump_name + "_debug_tree")
|
| 232 |
+
except Exception as e:
|
| 233 |
+
raise ValueError(f"Unexpected or existing debug_path={debug_path}.") from e
|
| 234 |
+
else:
|
| 235 |
+
base = model._debugger_module_dump_name + "_debug_tree"
|
| 236 |
+
|
| 237 |
+
logger.info(f"Writing model trace at {base}.json")
|
| 238 |
+
full_path = base + "_FULL_TENSORS.json"
|
| 239 |
+
summary_path = base + "_SUMMARY.json"
|
| 240 |
+
|
| 241 |
+
prune_outputs_if_children(model._call_tree)
|
| 242 |
+
|
| 243 |
+
with open(full_path, "w") as f:
|
| 244 |
+
json.dump(model._call_tree, f, indent=2)
|
| 245 |
+
|
| 246 |
+
# summary-only version for readability - traversing the tree again #TODO optimize?
|
| 247 |
+
def strip_values(node):
|
| 248 |
+
def clean(val):
|
| 249 |
+
if isinstance(val, dict):
|
| 250 |
+
val.pop("value", None)
|
| 251 |
+
for v in val.values():
|
| 252 |
+
clean(v)
|
| 253 |
+
elif isinstance(val, list):
|
| 254 |
+
for item in val:
|
| 255 |
+
clean(item)
|
| 256 |
+
|
| 257 |
+
clean(node.get("inputs", {}))
|
| 258 |
+
clean(node.get("outputs", {}))
|
| 259 |
+
|
| 260 |
+
for child in node.get("children", []):
|
| 261 |
+
strip_values(child)
|
| 262 |
+
|
| 263 |
+
tree_copy = json.loads(json.dumps(model._call_tree)) # deep copy
|
| 264 |
+
strip_values(tree_copy)
|
| 265 |
+
|
| 266 |
+
with open(summary_path, "w") as f:
|
| 267 |
+
json.dump(tree_copy, f, indent=2)
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
def _attach_debugger_logic(
|
| 271 |
+
model,
|
| 272 |
+
debug_path: str = ".",
|
| 273 |
+
do_prune_layers: bool = True,
|
| 274 |
+
use_repr: bool = True,
|
| 275 |
+
):
|
| 276 |
+
"""
|
| 277 |
+
Attaches a debugging wrapper to every module in the model.
|
| 278 |
+
|
| 279 |
+
This records structured inputs and outputs during the forward pass into a call tree.
|
| 280 |
+
|
| 281 |
+
Args:
|
| 282 |
+
model (`PreTrainedModel`, `nn.Module`): Model to wrap.
|
| 283 |
+
debug_path (`str`): Optional directory to dump debug JSON files.
|
| 284 |
+
do_prune_layers (`bool`, *optional*, defaults to `True`): Whether to prune intermediate layers.
|
| 285 |
+
use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensors as the
|
| 286 |
+
`value` property in the associated FULL_TENSORS.json file, or to store full tensors in separate SafeTensors
|
| 287 |
+
files and store the relative path to that file in the `value` property.
|
| 288 |
+
"""
|
| 289 |
+
class_name = model.__class__.__name__
|
| 290 |
+
|
| 291 |
+
# Prepare data structures on the model object
|
| 292 |
+
model._call_tree = {"module_path": class_name, "inputs": None, "outputs": None, "children": []}
|
| 293 |
+
model._debugger_model_call_stack = []
|
| 294 |
+
model._debugger_module_dump_name = class_name # used for final JSON filename
|
| 295 |
+
|
| 296 |
+
if debug_path:
|
| 297 |
+
try:
|
| 298 |
+
os.makedirs(debug_path, exist_ok=True)
|
| 299 |
+
except Exception as e:
|
| 300 |
+
raise ValueError(f"Unexpected or existing debug_path={debug_path}.") from e
|
| 301 |
+
|
| 302 |
+
def wrap_forward(module, full_path):
|
| 303 |
+
orig_forward = module.forward
|
| 304 |
+
|
| 305 |
+
@functools.wraps(orig_forward)
|
| 306 |
+
def wrapped_forward(*inps, **kws):
|
| 307 |
+
if _is_rank_zero():
|
| 308 |
+
dict_inputs = {"args": inps, "kwargs": kws}
|
| 309 |
+
dict_inputs = {k: dict_inputs[k] for k in dict_inputs if len(dict_inputs[k]) > 0}
|
| 310 |
+
node = {
|
| 311 |
+
"module_path": full_path,
|
| 312 |
+
"inputs": _serialize_io(
|
| 313 |
+
dict_inputs,
|
| 314 |
+
debug_path=debug_path,
|
| 315 |
+
use_repr=use_repr,
|
| 316 |
+
path_to_value=f"{full_path}_inputs",
|
| 317 |
+
),
|
| 318 |
+
"outputs": None,
|
| 319 |
+
"children": [],
|
| 320 |
+
}
|
| 321 |
+
model._debugger_model_call_stack.append(node)
|
| 322 |
+
with torch.no_grad():
|
| 323 |
+
out = orig_forward(*inps, **kws)
|
| 324 |
+
|
| 325 |
+
if _is_rank_zero():
|
| 326 |
+
if sum(1 for _ in module.named_children()) > 0:
|
| 327 |
+
node["outputs"] = None
|
| 328 |
+
else:
|
| 329 |
+
node["outputs"] = _serialize_io(
|
| 330 |
+
out,
|
| 331 |
+
debug_path=debug_path,
|
| 332 |
+
use_repr=use_repr,
|
| 333 |
+
path_to_value=f"{full_path}_outputs",
|
| 334 |
+
)
|
| 335 |
+
|
| 336 |
+
finished = model._debugger_model_call_stack.pop()
|
| 337 |
+
# prune empty vertices here as well (mostly empty children nodes)
|
| 338 |
+
if not finished["children"]:
|
| 339 |
+
finished.pop("children")
|
| 340 |
+
|
| 341 |
+
if model._debugger_model_call_stack:
|
| 342 |
+
model._debugger_model_call_stack[-1]["children"].append(finished)
|
| 343 |
+
return out
|
| 344 |
+
|
| 345 |
+
module.forward = wrapped_forward
|
| 346 |
+
|
| 347 |
+
# wrap all submodules
|
| 348 |
+
for name, submodule in model.named_modules():
|
| 349 |
+
if name == "":
|
| 350 |
+
continue
|
| 351 |
+
wrap_forward(submodule, f"{class_name}.{name}")
|
| 352 |
+
|
| 353 |
+
# wrap top-level forward
|
| 354 |
+
real_top_forward = model.forward
|
| 355 |
+
|
| 356 |
+
@functools.wraps(real_top_forward)
|
| 357 |
+
def top_wrapped_forward(*inps, **kws):
|
| 358 |
+
if _is_rank_zero():
|
| 359 |
+
top_node = {
|
| 360 |
+
"module_path": f"{class_name} (top-level)",
|
| 361 |
+
"inputs": _serialize_io(
|
| 362 |
+
{"args": inps, "kwargs": kws},
|
| 363 |
+
debug_path=debug_path,
|
| 364 |
+
use_repr=use_repr,
|
| 365 |
+
path_to_value=f"{class_name}_inputs",
|
| 366 |
+
),
|
| 367 |
+
"outputs": None,
|
| 368 |
+
"children": [],
|
| 369 |
+
}
|
| 370 |
+
model._debugger_model_call_stack.append(top_node)
|
| 371 |
+
|
| 372 |
+
out = real_top_forward(*inps, **kws)
|
| 373 |
+
if _is_rank_zero() and model._debugger_model_call_stack:
|
| 374 |
+
top_node["outputs"] = _serialize_io(
|
| 375 |
+
out,
|
| 376 |
+
debug_path=debug_path,
|
| 377 |
+
use_repr=use_repr,
|
| 378 |
+
path_to_value=f"{class_name}_outputs",
|
| 379 |
+
)
|
| 380 |
+
finished = model._debugger_model_call_stack.pop()
|
| 381 |
+
model._call_tree["inputs"] = finished["inputs"]
|
| 382 |
+
model._call_tree["outputs"] = finished["outputs"]
|
| 383 |
+
model._call_tree["children"] = finished["children"]
|
| 384 |
+
# prune empty stuff for visibility
|
| 385 |
+
[model._call_tree.pop(k, None) for k in list(model._call_tree.keys()) if not model._call_tree[k]]
|
| 386 |
+
|
| 387 |
+
# prune layers that are not 0 or last
|
| 388 |
+
if do_prune_layers:
|
| 389 |
+
prune_intermediate_layers(model._call_tree)
|
| 390 |
+
# Write final JSON trace here
|
| 391 |
+
log_model_debug_trace(debug_path=debug_path, model=model)
|
| 392 |
+
return out
|
| 393 |
+
|
| 394 |
+
model.forward = top_wrapped_forward
|
| 395 |
+
|
| 396 |
+
|
| 397 |
+
@requires(backends=("torch",))
|
| 398 |
+
@contextmanager
|
| 399 |
+
def model_addition_debugger_context(
|
| 400 |
+
model,
|
| 401 |
+
debug_path: str | None = None,
|
| 402 |
+
do_prune_layers: bool = True,
|
| 403 |
+
use_repr: bool = True,
|
| 404 |
+
):
|
| 405 |
+
"""
|
| 406 |
+
# Model addition debugger - context manager for model adders
|
| 407 |
+
This context manager is a power user tool intended for model adders.
|
| 408 |
+
|
| 409 |
+
It tracks all forward calls within a model forward and logs a slice of each input and output on a nested JSON file.
|
| 410 |
+
If `use_repr=True` (the default), the JSON file will record a `repr()`-ized version of the tensors as a list of
|
| 411 |
+
strings. If `use_repr=False`, the full tensors will be stored in separate SafeTensors files and the JSON file will
|
| 412 |
+
provide a relative path to that file.
|
| 413 |
+
|
| 414 |
+
To note, this context manager enforces `torch.no_grad()`.
|
| 415 |
+
|
| 416 |
+
## Usage
|
| 417 |
+
|
| 418 |
+
add the context manager to a model to debug
|
| 419 |
+
|
| 420 |
+
```python
|
| 421 |
+
import torch
|
| 422 |
+
|
| 423 |
+
from PIL import Image
|
| 424 |
+
from transformers import LlavaProcessor, LlavaForConditionalGeneration, model_addition_debugger_context
|
| 425 |
+
|
| 426 |
+
torch.random.manual_seed(673)
|
| 427 |
+
|
| 428 |
+
# load pretrained model and processor
|
| 429 |
+
model_id = "llava-hf/llava-1.5-7b-hf"
|
| 430 |
+
processor = LlavaProcessor.from_pretrained(model_id)
|
| 431 |
+
model = LlavaForConditionalGeneration.from_pretrained(model_id)
|
| 432 |
+
|
| 433 |
+
# create random image input
|
| 434 |
+
random_image = Image.fromarray(torch.randint(0, 256, (224, 224, 3), dtype=torch.uint8).numpy())
|
| 435 |
+
|
| 436 |
+
# prompt
|
| 437 |
+
prompt = "<image>Describe this image."
|
| 438 |
+
|
| 439 |
+
# process inputs
|
| 440 |
+
inputs = processor(text=prompt, images=random_image, return_tensors="pt")
|
| 441 |
+
|
| 442 |
+
# call forward method (not .generate!)
|
| 443 |
+
with model_addition_debugger_context(model, debug_path="Your_debug_path", do_prune_layers=False):
|
| 444 |
+
output = model.forward(**inputs)
|
| 445 |
+
```
|
| 446 |
+
|
| 447 |
+
"""
|
| 448 |
+
orig_forwards = {m: m.forward for _, m in model.named_modules()}
|
| 449 |
+
orig_forwards[model] = model.forward
|
| 450 |
+
_attach_debugger_logic(model, debug_path, do_prune_layers, use_repr)
|
| 451 |
+
try:
|
| 452 |
+
yield model
|
| 453 |
+
finally:
|
| 454 |
+
for module_instance, forward_method in orig_forwards.items():
|
| 455 |
+
module_instance.forward = forward_method
|
third_party/transformers/src/transformers/modeling_flash_attention_utils.py
ADDED
|
@@ -0,0 +1,807 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The Fairseq Authors and the HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
import importlib
|
| 15 |
+
import inspect
|
| 16 |
+
import os
|
| 17 |
+
from collections.abc import Callable
|
| 18 |
+
from functools import partial
|
| 19 |
+
from typing import TypedDict
|
| 20 |
+
|
| 21 |
+
import torch
|
| 22 |
+
import torch.nn.functional as F
|
| 23 |
+
|
| 24 |
+
from .utils import (
|
| 25 |
+
is_flash_attn_2_available,
|
| 26 |
+
is_flash_attn_3_available,
|
| 27 |
+
is_flash_attn_4_available,
|
| 28 |
+
is_torch_cuda_available,
|
| 29 |
+
is_torch_mlu_available,
|
| 30 |
+
is_torch_npu_available,
|
| 31 |
+
is_torch_xpu_available,
|
| 32 |
+
logging,
|
| 33 |
+
)
|
| 34 |
+
from .utils.import_utils import PACKAGE_DISTRIBUTION_MAPPING, is_tracing
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
logger = logging.get_logger(__name__)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
# TODO Deprecate when all models have the attention interface
|
| 41 |
+
def flash_attn_supports_top_left_mask():
|
| 42 |
+
if is_flash_attn_2_available() or is_flash_attn_3_available() or is_flash_attn_4_available():
|
| 43 |
+
return False
|
| 44 |
+
|
| 45 |
+
from .integrations.npu_flash_attention import is_npu_fa2_top_left_aligned_causal_mask
|
| 46 |
+
|
| 47 |
+
return is_npu_fa2_top_left_aligned_causal_mask()
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# TODO Deprecate when all models have the attention interface
|
| 51 |
+
def is_flash_attn_available():
|
| 52 |
+
return (
|
| 53 |
+
is_flash_attn_4_available()
|
| 54 |
+
or is_flash_attn_3_available()
|
| 55 |
+
or is_flash_attn_2_available()
|
| 56 |
+
or is_torch_npu_available()
|
| 57 |
+
or is_torch_xpu_available()
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
# Mapping from flash attention implementations to their kernel fallback repositories
|
| 62 |
+
FLASH_ATTN_KERNEL_FALLBACK = {
|
| 63 |
+
"flash_attention_2": "kernels-community/flash-attn2",
|
| 64 |
+
"flash_attention_3": "kernels-community/vllm-flash-attn3",
|
| 65 |
+
"flash_attention_4": "kernels-community/flash-attn4",
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
# Meta information on each mainline FA compatibility:
|
| 70 |
+
# 1. The import structure and availability
|
| 71 |
+
# 2. Device support (with custom ones that use other workarounds, e.g. kernels)
|
| 72 |
+
# 3. Supported major cuda devices, e.g. Hopper, Blackwell. Mostly found in the newest FA versions
|
| 73 |
+
FLASH_ATTENTION_COMPATIBILITY_MATRIX = {
|
| 74 |
+
2: {
|
| 75 |
+
"flash_attn_version": 2,
|
| 76 |
+
"general_availability_check": is_flash_attn_2_available,
|
| 77 |
+
"pkg_availability_check": lambda *args, **kwargs: importlib.util.find_spec("flash_attn") is not None
|
| 78 |
+
and "flash-attn" in [pkg.replace("_", "-") for pkg in PACKAGE_DISTRIBUTION_MAPPING["flash_attn"]],
|
| 79 |
+
"supported_devices": (
|
| 80 |
+
(is_torch_cuda_available, "cuda"),
|
| 81 |
+
(is_torch_mlu_available, "mlu"),
|
| 82 |
+
(is_torch_npu_available, "npu"),
|
| 83 |
+
(is_torch_xpu_available, "xpu"),
|
| 84 |
+
),
|
| 85 |
+
"custom_supported_devices": (
|
| 86 |
+
(is_torch_npu_available, "Detect using FlashAttention2 on Ascend NPU."),
|
| 87 |
+
(
|
| 88 |
+
is_torch_xpu_available,
|
| 89 |
+
f"Detect using FlashAttention2 (via kernel `{FLASH_ATTN_KERNEL_FALLBACK['flash_attention_2']}`) on XPU.",
|
| 90 |
+
),
|
| 91 |
+
),
|
| 92 |
+
},
|
| 93 |
+
3: {
|
| 94 |
+
"flash_attn_version": 3,
|
| 95 |
+
"general_availability_check": is_flash_attn_3_available,
|
| 96 |
+
"pkg_availability_check": lambda *args, **kwargs: importlib.util.find_spec("flash_attn_interface") is not None
|
| 97 |
+
and "flash-attn-3" in [pkg.replace("_", "-") for pkg in PACKAGE_DISTRIBUTION_MAPPING["flash_attn_interface"]],
|
| 98 |
+
"supported_devices": ((is_torch_cuda_available, "cuda"),),
|
| 99 |
+
"cuda_min_major_version": 8, # Ampere
|
| 100 |
+
},
|
| 101 |
+
4: {
|
| 102 |
+
"flash_attn_version": 4,
|
| 103 |
+
"general_availability_check": is_flash_attn_4_available,
|
| 104 |
+
"pkg_availability_check": lambda *args, **kwargs: importlib.util.find_spec("flash_attn") is not None
|
| 105 |
+
and "flash-attn-4" in [pkg.replace("_", "-") for pkg in PACKAGE_DISTRIBUTION_MAPPING["flash_attn"]],
|
| 106 |
+
"supported_devices": ((is_torch_cuda_available, "cuda"),),
|
| 107 |
+
"cuda_min_major_version": 9, # Hopper
|
| 108 |
+
},
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
# `globals()` is not compatible with dynamo, hence we have do define them in global scope ourselves
|
| 113 |
+
_loaded_implementation = None
|
| 114 |
+
_flash_fn = None
|
| 115 |
+
_flash_varlen_fn = None
|
| 116 |
+
_flash_with_kvcache_fn = None
|
| 117 |
+
_pad_fn = None
|
| 118 |
+
_unpad_fn = None
|
| 119 |
+
|
| 120 |
+
# function that processes kwargs, generalized to handle any supported kwarg within the function
|
| 121 |
+
_process_flash_kwargs_fn = None
|
| 122 |
+
# exceptions where hf API doesn't match the original flash attention API
|
| 123 |
+
_hf_api_to_flash_mapping = {
|
| 124 |
+
"dropout": "dropout_p",
|
| 125 |
+
"sliding_window": "window_size",
|
| 126 |
+
}
|
| 127 |
+
# alternative names within the different flash attention APIs, e.g. for attention sinks
|
| 128 |
+
_flash_api_alternative_names = {"s_aux": "learnable_sink"}
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def _lazy_imports(
|
| 132 |
+
implementation: str | None, attention_wrapper: Callable | None = None, allow_all_kernels: bool = False
|
| 133 |
+
):
|
| 134 |
+
"""
|
| 135 |
+
Lazy loads the respective flash attention implementations.
|
| 136 |
+
|
| 137 |
+
Return:
|
| 138 |
+
flash_attn_func: The base flash attention function.
|
| 139 |
+
flash_attn_varlen_func: The flash attention function supporting variable sequence lengths,
|
| 140 |
+
e.g. for padding-free training.
|
| 141 |
+
pad_input: The function to pad inputs into one sequence and returning the respective kwargs.
|
| 142 |
+
unpad_input: The function to unpad outputs based on the kwargs (from pad_input).
|
| 143 |
+
"""
|
| 144 |
+
is_fa2 = is_flash_attn_2_available()
|
| 145 |
+
is_fa3 = is_flash_attn_3_available()
|
| 146 |
+
is_fa4 = is_flash_attn_4_available()
|
| 147 |
+
|
| 148 |
+
pad_input, unpad_input = _pad_input, _unpad_input
|
| 149 |
+
|
| 150 |
+
is_paged = implementation.startswith("paged|")
|
| 151 |
+
implementation = implementation.split("|")[1] if is_paged else implementation
|
| 152 |
+
|
| 153 |
+
if (implementation == "flash_attention_2" and is_fa2) or (
|
| 154 |
+
implementation is None and is_fa2 and not is_fa3 and not is_fa4
|
| 155 |
+
):
|
| 156 |
+
from flash_attn import flash_attn_func, flash_attn_varlen_func, flash_attn_with_kvcache
|
| 157 |
+
from flash_attn.bert_padding import pad_input, unpad_input
|
| 158 |
+
elif is_torch_npu_available():
|
| 159 |
+
# Package `flash-attn` is unavailable on Ascend NPU, which will cause ImportError
|
| 160 |
+
# Flash-Attention2 related apis for Ascend NPU must be imported from `.integrations.npu_flash_attention` module
|
| 161 |
+
from .integrations.npu_flash_attention import npu_flash_attn_func as flash_attn_func
|
| 162 |
+
from .integrations.npu_flash_attention import npu_flash_attn_varlen_func as flash_attn_varlen_func
|
| 163 |
+
from .integrations.npu_flash_attention import npu_flash_attn_with_kvcache as flash_attn_with_kvcache
|
| 164 |
+
else:
|
| 165 |
+
if implementation == "flash_attention_3" or (implementation is None and is_fa3 and not is_fa4):
|
| 166 |
+
from flash_attn_interface import flash_attn_func, flash_attn_varlen_func, flash_attn_with_kvcache
|
| 167 |
+
elif implementation == "flash_attention_4" or (implementation is None and is_fa4):
|
| 168 |
+
from flash_attn.cute import flash_attn_func, flash_attn_varlen_func
|
| 169 |
+
|
| 170 |
+
flash_attn_with_kvcache = None # not supported yet
|
| 171 |
+
# Kernels fallback
|
| 172 |
+
else:
|
| 173 |
+
from .integrations.hub_kernels import load_and_register_attn_kernel
|
| 174 |
+
|
| 175 |
+
# Map standard attention names to hub kernel repos
|
| 176 |
+
kernel_repo = FLASH_ATTN_KERNEL_FALLBACK.get(implementation, implementation)
|
| 177 |
+
# We want to explicitly register the name with `paged|` if found
|
| 178 |
+
kernel_implementation = f"paged|{implementation}" if is_paged else kernel_repo
|
| 179 |
+
kernel = load_and_register_attn_kernel(
|
| 180 |
+
kernel_implementation, attention_wrapper, allow_all_kernels=allow_all_kernels
|
| 181 |
+
)
|
| 182 |
+
|
| 183 |
+
flash_attn_func = getattr(kernel, "flash_attn_func", None)
|
| 184 |
+
flash_attn_varlen_func = getattr(kernel, "flash_attn_varlen_func", None)
|
| 185 |
+
flash_attn_with_kvcache = getattr(kernel, "flash_attn_with_kvcache", None)
|
| 186 |
+
if flash_attn_varlen_func is None:
|
| 187 |
+
raise ValueError(
|
| 188 |
+
f"Could not find the currently requested flash attention implementation at `{implementation}`."
|
| 189 |
+
"Make sure that you request a valid kernel from the hub, e.g. `kernels-community/flash-attn2`."
|
| 190 |
+
)
|
| 191 |
+
if flash_attn_func is None:
|
| 192 |
+
logger.warning(
|
| 193 |
+
f"The loaded flash attention implementation at `{implementation}` only supports varlen, i.e. "
|
| 194 |
+
"it can only be used with continuous batching and does not support the full functionality for "
|
| 195 |
+
"the base transformers generation methods."
|
| 196 |
+
)
|
| 197 |
+
if flash_attn_with_kvcache is None:
|
| 198 |
+
logger.warning(
|
| 199 |
+
f"The loaded flash attention implementation at `{implementation}` does not support block tables, so"
|
| 200 |
+
" the full performances of continuous batching will not be achieved, only the varlen path will be "
|
| 201 |
+
"used."
|
| 202 |
+
)
|
| 203 |
+
|
| 204 |
+
return flash_attn_func, flash_attn_varlen_func, flash_attn_with_kvcache, pad_input, unpad_input
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
def _lazy_define_process_function(flash_function):
|
| 208 |
+
"""
|
| 209 |
+
Depending on the version and kernel some features are not supported. Due to limitations in
|
| 210 |
+
`torch.compile`, we opt to statically type which (optional) kwarg parameters are supported
|
| 211 |
+
within `_process_flash_attention_kwargs`.
|
| 212 |
+
|
| 213 |
+
NOTE: While all supported kwargs are marked as `True`, everything else is marked as `False`.
|
| 214 |
+
This might be confusing for kwargs that we use in any case, e.g. `is_causal`.
|
| 215 |
+
"""
|
| 216 |
+
|
| 217 |
+
flash_parameters = inspect.signature(flash_function).parameters
|
| 218 |
+
process_parameters = inspect.signature(_process_flash_attention_kwargs).parameters
|
| 219 |
+
|
| 220 |
+
supports_mapping = {}
|
| 221 |
+
for param in process_parameters:
|
| 222 |
+
fa_param = _hf_api_to_flash_mapping.get(param, param)
|
| 223 |
+
supports_mapping[fa_param] = fa_param in flash_parameters
|
| 224 |
+
|
| 225 |
+
if (fa_alternative_name := _flash_api_alternative_names.get(param, param)) != fa_param:
|
| 226 |
+
supports_mapping[fa_alternative_name] = fa_alternative_name in flash_parameters
|
| 227 |
+
|
| 228 |
+
return partial(_process_flash_attention_kwargs, supports_mapping=supports_mapping)
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
def lazy_import_flash_attention(
|
| 232 |
+
implementation: str | None, attention_wrapper: Callable | None = None, allow_all_kernels: bool = False
|
| 233 |
+
):
|
| 234 |
+
"""
|
| 235 |
+
Lazily import flash attention and return the respective functions + flags.
|
| 236 |
+
|
| 237 |
+
NOTE: For fullgraph, this needs to be called before compile, while no fullgraph can
|
| 238 |
+
work without preloading. See `load_and_register_attn_kernel` in `integrations.hub_kernels`.
|
| 239 |
+
"""
|
| 240 |
+
global _loaded_implementation
|
| 241 |
+
if implementation is None and _loaded_implementation is None:
|
| 242 |
+
raise ValueError("Could not find any flash attn implementation based on your environment.")
|
| 243 |
+
|
| 244 |
+
global _flash_fn, _flash_varlen_fn, _flash_with_kvcache_fn, _pad_fn, _unpad_fn, _process_flash_kwargs_fn
|
| 245 |
+
if implementation is not None and _loaded_implementation != implementation:
|
| 246 |
+
_loaded_implementation = implementation
|
| 247 |
+
|
| 248 |
+
_flash_fn, _flash_varlen_fn, _flash_with_kvcache_fn, _pad_fn, _unpad_fn = _lazy_imports(
|
| 249 |
+
implementation, attention_wrapper, allow_all_kernels=allow_all_kernels
|
| 250 |
+
)
|
| 251 |
+
_process_flash_kwargs_fn = _lazy_define_process_function(_flash_varlen_fn)
|
| 252 |
+
|
| 253 |
+
return (_flash_fn, _flash_varlen_fn, _flash_with_kvcache_fn, _pad_fn, _unpad_fn), _process_flash_kwargs_fn
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
def lazy_import_paged_flash_attention(implementation: str | None, allow_all_kernels: bool = False):
|
| 257 |
+
"""
|
| 258 |
+
Same as `lazy_import_flash_attention` but explicitly wrapping it with the paged implementation.
|
| 259 |
+
"""
|
| 260 |
+
from .integrations.flash_paged import paged_attention_forward
|
| 261 |
+
|
| 262 |
+
(_, flash_attn_varlen_func, flash_attn_with_kvcache_fn, _, _), _ = lazy_import_flash_attention(
|
| 263 |
+
implementation, attention_wrapper=paged_attention_forward, allow_all_kernels=allow_all_kernels
|
| 264 |
+
)
|
| 265 |
+
return flash_attn_varlen_func, flash_attn_with_kvcache_fn
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
def _index_first_axis(tensor, indices):
|
| 269 |
+
"""
|
| 270 |
+
A local implementation of the PyTorch indexing operation `tensor[indices]` on the first axis,
|
| 271 |
+
after flattening the first two dimensions of the tensor. This is functionally equivalent to
|
| 272 |
+
FA2's `index_first_axis` and replaces the need to import it.
|
| 273 |
+
"""
|
| 274 |
+
# The input tensor is expected to be of shape (batch, seq_len, ...). We flatten the first
|
| 275 |
+
# two dimensions to get (total_tokens, ...) before indexing.
|
| 276 |
+
reshaped_tensor = tensor.reshape(-1, *tensor.shape[2:])
|
| 277 |
+
return reshaped_tensor[indices]
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
def _unpad_input(hidden_states, attention_mask, unused_mask=None):
|
| 281 |
+
"""
|
| 282 |
+
unpad_input function for flash attention variants that do not have them within their pkg themselves, e.g. fa3.
|
| 283 |
+
|
| 284 |
+
Arguments:
|
| 285 |
+
hidden_states: (batch, seqlen, ...)
|
| 286 |
+
attention_mask: (batch, seqlen), bool / int, 1 means valid and 0 means not valid.
|
| 287 |
+
unused_mask: (batch, seqlen), bool / int, 1 means the element is allocated but unused.
|
| 288 |
+
|
| 289 |
+
Return:
|
| 290 |
+
hidden_states: (total_nnz, ...), where total_nnz = number of tokens selected in attention_mask + unused_mask.
|
| 291 |
+
indices: (total_nnz), the indices of masked tokens from the flattened input sequence.
|
| 292 |
+
cu_seqlens: (batch + 1), the cumulative sequence lengths, used to index into hidden_states.
|
| 293 |
+
max_seqlen_in_batch: int
|
| 294 |
+
seqused: (batch), returns the number of tokens selected in attention_mask + unused_mask.
|
| 295 |
+
"""
|
| 296 |
+
all_masks = (attention_mask + unused_mask) if unused_mask is not None else attention_mask
|
| 297 |
+
seqlens_in_batch = all_masks.sum(dim=-1, dtype=torch.int32)
|
| 298 |
+
used_seqlens_in_batch = attention_mask.sum(dim=-1, dtype=torch.int32)
|
| 299 |
+
indices = torch.nonzero(all_masks.flatten(), as_tuple=False).flatten()
|
| 300 |
+
max_seqlen_in_batch = seqlens_in_batch.max()
|
| 301 |
+
cu_seqlens = F.pad(torch.cumsum(seqlens_in_batch, dim=0, dtype=torch.int32), (1, 0))
|
| 302 |
+
|
| 303 |
+
return (
|
| 304 |
+
_index_first_axis(hidden_states, indices),
|
| 305 |
+
indices,
|
| 306 |
+
cu_seqlens,
|
| 307 |
+
max_seqlen_in_batch,
|
| 308 |
+
used_seqlens_in_batch,
|
| 309 |
+
)
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
def _pad_input(hidden_states, indices, batch, seqlen):
|
| 313 |
+
"""
|
| 314 |
+
pad_input function for flash attention variants that do not have them within their pkg themselves, e.g. fa3.
|
| 315 |
+
|
| 316 |
+
Arguments:
|
| 317 |
+
hidden_states: (total_nnz, ...), where total_nnz = number of tokens in selected in attention_mask.
|
| 318 |
+
indices: (total_nnz), the indices that represent the non-masked tokens of the original padded input sequence.
|
| 319 |
+
batch: int, batch size for the padded sequence.
|
| 320 |
+
seqlen: int, maximum sequence length for the padded sequence.
|
| 321 |
+
|
| 322 |
+
Return:
|
| 323 |
+
hidden_states: (batch, seqlen, ...)
|
| 324 |
+
"""
|
| 325 |
+
dim = hidden_states.shape[1:]
|
| 326 |
+
output = torch.zeros((batch * seqlen), *dim, device=hidden_states.device, dtype=hidden_states.dtype)
|
| 327 |
+
output[indices] = hidden_states
|
| 328 |
+
return output.view(batch, seqlen, *dim)
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
def _get_unpad_data(attention_mask: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, int]:
|
| 332 |
+
"""
|
| 333 |
+
Retrieves indexing data required to repad unpadded (ragged) tensors.
|
| 334 |
+
|
| 335 |
+
Arguments:
|
| 336 |
+
attention_mask (`torch.Tensor`):
|
| 337 |
+
Boolean or int tensor of shape (batch_size, sequence_length), 1 means valid and 0 means not valid.
|
| 338 |
+
|
| 339 |
+
Return:
|
| 340 |
+
indices (`torch.Tensor`):
|
| 341 |
+
The indices of non-masked tokens from the flattened input sequence.
|
| 342 |
+
cu_seqlens (`torch.Tensor`):
|
| 343 |
+
The cumulative sequence lengths, used to index into ragged (unpadded) tensors. `cu_seqlens` shape is (batch_size + 1,).
|
| 344 |
+
max_seqlen_in_batch (`int`):
|
| 345 |
+
Maximum sequence length in batch.
|
| 346 |
+
"""
|
| 347 |
+
seqlens_in_batch = attention_mask.sum(dim=-1, dtype=torch.int32)
|
| 348 |
+
indices = torch.nonzero(attention_mask.flatten(), as_tuple=False).flatten()
|
| 349 |
+
max_seqlen_in_batch = seqlens_in_batch.max()
|
| 350 |
+
cu_seqlens = F.pad(torch.cumsum(seqlens_in_batch, dim=0, dtype=torch.int32), (1, 0))
|
| 351 |
+
return (
|
| 352 |
+
indices,
|
| 353 |
+
cu_seqlens,
|
| 354 |
+
max_seqlen_in_batch,
|
| 355 |
+
)
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
def _upad_input(
|
| 359 |
+
query_layer: torch.Tensor,
|
| 360 |
+
key_layer: torch.Tensor,
|
| 361 |
+
value_layer: torch.Tensor,
|
| 362 |
+
attention_mask: torch.Tensor,
|
| 363 |
+
query_length: int,
|
| 364 |
+
unpad_input_func,
|
| 365 |
+
):
|
| 366 |
+
"""
|
| 367 |
+
Unpads query, key, and values tensors, using a single dimension for all tokens even though they belong to different batches.
|
| 368 |
+
This function is used instead of `flash_attn.bert_padding.unpad_input` in order to avoid the recomputation of the same intermediary
|
| 369 |
+
tensors for query, key, value tensors.
|
| 370 |
+
|
| 371 |
+
Arguments:
|
| 372 |
+
query_layer (`torch.Tensor`):
|
| 373 |
+
Query state with padding. Shape: (batch_size, query_length, num_heads, head_dim).
|
| 374 |
+
key_layer (`torch.Tensor`):
|
| 375 |
+
Key state with padding. Shape: (batch_size, kv_seq_len, num_key_value_heads, head_dim).
|
| 376 |
+
value_layer (`torch.Tensor`):
|
| 377 |
+
Value state with padding. Shape: (batch_size, kv_seq_len, num_key_value_heads, head_dim).
|
| 378 |
+
attention_mask (`torch.Tensor`):
|
| 379 |
+
Boolean or int tensor of shape (batch_size, sequence_length), 1 means valid and 0 means not valid.
|
| 380 |
+
query_length (`int`):
|
| 381 |
+
Target length.
|
| 382 |
+
unpad_input_func:
|
| 383 |
+
The function to use for unpadding the input tensors.
|
| 384 |
+
|
| 385 |
+
Return:
|
| 386 |
+
query_layer (`torch.Tensor`):
|
| 387 |
+
Query state without padding. Shape: (total_target_length, num_heads, head_dim).
|
| 388 |
+
key_layer (`torch.Tensor`):
|
| 389 |
+
Key state with padding. Shape: (total_source_length, num_key_value_heads, head_dim).
|
| 390 |
+
value_layer (`torch.Tensor`):
|
| 391 |
+
Value state with padding. Shape: (total_source_length, num_key_value_heads, head_dim).
|
| 392 |
+
indices_q (`torch.Tensor`):
|
| 393 |
+
The indices of non-masked tokens from the flattened input target sequence.
|
| 394 |
+
(cu_seqlens_q, cu_seqlens_k) (`tuple[int]`):
|
| 395 |
+
The cumulative sequence lengths for the target (query) and source (key, value), used to index into ragged (unpadded) tensors. `cu_seqlens` shape is (batch_size + 1,).
|
| 396 |
+
(max_seqlen_in_batch_q, max_seqlen_in_batch_k) (`tuple[int]`):
|
| 397 |
+
Maximum sequence length in batch (`max_seqlen_in_batch_q` for the target sequence i.e. query, `max_seqlen_in_batch_k` for the source sequence i.e. key/value).
|
| 398 |
+
"""
|
| 399 |
+
indices_k, cu_seqlens_k, max_seqlen_in_batch_k = _get_unpad_data(attention_mask)
|
| 400 |
+
|
| 401 |
+
# With static caches, the k/v states may be larger than the mask -> we need to slice them to avoid generating garbage
|
| 402 |
+
# It's a bit of an anti-pattern, but otherwise we silently compute wrong attentions scores
|
| 403 |
+
if key_layer.shape[1] > (seq_len := attention_mask.shape[-1]):
|
| 404 |
+
key_layer, value_layer = key_layer[:, :seq_len, :, :], value_layer[:, :seq_len, :, :]
|
| 405 |
+
|
| 406 |
+
batch_size, kv_seq_len, num_key_value_heads, head_dim = key_layer.shape
|
| 407 |
+
|
| 408 |
+
key_layer = _index_first_axis(key_layer, indices_k)
|
| 409 |
+
value_layer = _index_first_axis(value_layer, indices_k)
|
| 410 |
+
if query_length == kv_seq_len:
|
| 411 |
+
query_layer = _index_first_axis(query_layer, indices_k)
|
| 412 |
+
cu_seqlens_q = cu_seqlens_k
|
| 413 |
+
max_seqlen_in_batch_q = max_seqlen_in_batch_k
|
| 414 |
+
indices_q = indices_k
|
| 415 |
+
elif query_length == 1:
|
| 416 |
+
max_seqlen_in_batch_q = 1
|
| 417 |
+
cu_seqlens_q = torch.arange(
|
| 418 |
+
batch_size + 1, dtype=torch.int32, device=query_layer.device
|
| 419 |
+
) # There is a memcpy here, that is very bad.
|
| 420 |
+
indices_q = cu_seqlens_q[:-1]
|
| 421 |
+
query_layer = query_layer.squeeze(1)
|
| 422 |
+
else:
|
| 423 |
+
# The -q_len: slice assumes left padding.
|
| 424 |
+
attention_mask = attention_mask[:, -query_length:]
|
| 425 |
+
query_layer, indices_q, cu_seqlens_q, max_seqlen_in_batch_q, *_ = unpad_input_func(query_layer, attention_mask)
|
| 426 |
+
|
| 427 |
+
return (
|
| 428 |
+
query_layer,
|
| 429 |
+
key_layer,
|
| 430 |
+
value_layer,
|
| 431 |
+
indices_q,
|
| 432 |
+
(cu_seqlens_q, cu_seqlens_k),
|
| 433 |
+
(max_seqlen_in_batch_q, max_seqlen_in_batch_k),
|
| 434 |
+
)
|
| 435 |
+
|
| 436 |
+
|
| 437 |
+
def prepare_fa_kwargs_from_position_ids(position_ids):
|
| 438 |
+
"""
|
| 439 |
+
This function returns all the necessary kwargs to call `flash_attn_varlen_func` extracted from position_ids.
|
| 440 |
+
|
| 441 |
+
Arguments:
|
| 442 |
+
position_ids (`torch.Tensor`):
|
| 443 |
+
Boolean or int tensor of shape (batch_size, sequence_length), 1 means valid and 0 means not valid.
|
| 444 |
+
|
| 445 |
+
Return:
|
| 446 |
+
(cu_seqlens_q, cu_seqlens_k) (`tuple[int]`):
|
| 447 |
+
The cumulative sequence lengths for the target (query) and source (key, value), used to index into
|
| 448 |
+
ragged (unpadded) tensors. `cu_seqlens` shape is (batch_size + 1,).
|
| 449 |
+
(max_seqlen_in_batch_q, max_seqlen_in_batch_k) (`tuple[int]`):
|
| 450 |
+
Maximum sequence length in batch (`max_seqlen_in_batch_q` for the target sequence i.e. query,
|
| 451 |
+
`max_seqlen_in_batch_k` for the source sequence i.e. key/value).
|
| 452 |
+
"""
|
| 453 |
+
tensor_kwargs = {"dtype": torch.int32, "device": position_ids.device}
|
| 454 |
+
|
| 455 |
+
position_ids = position_ids.reshape(-1)
|
| 456 |
+
indices_q = (position_ids == 0).nonzero().view(-1)
|
| 457 |
+
|
| 458 |
+
cu_seq_lens_q = torch.cat(
|
| 459 |
+
(
|
| 460 |
+
indices_q.to(**tensor_kwargs),
|
| 461 |
+
torch.tensor(position_ids.size(), **tensor_kwargs),
|
| 462 |
+
)
|
| 463 |
+
)
|
| 464 |
+
cu_seq_lens_k = cu_seq_lens_q
|
| 465 |
+
|
| 466 |
+
# https://github.com/Dao-AILab/flash-attention/blob/2dd8078adc1d9b74e315ee99718c0dea0de8eeb6/flash_attn/flash_attn_interface.py#L1423-L1424
|
| 467 |
+
# We should use cu_seq_lens instead of position_ids to get the max length since position_ids is not always increasing
|
| 468 |
+
# for some models (e.g. qwen2-vl).
|
| 469 |
+
max_length_q = cu_seq_lens_q.diff().max()
|
| 470 |
+
max_length_k = max_length_q
|
| 471 |
+
|
| 472 |
+
return (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k)
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
def _prepare_from_posids(query, key, value, position_ids):
|
| 476 |
+
"""
|
| 477 |
+
This function returns necessary arguments to call `flash_attn_varlen_func`.
|
| 478 |
+
All three query, key, value states will be flattened.
|
| 479 |
+
Cumulative lengths of each examples in the batch will be extracted from position_ids.
|
| 480 |
+
NOTE: ideally cumulative lengths should be prepared at the data collator stage
|
| 481 |
+
|
| 482 |
+
Arguments:
|
| 483 |
+
query (`torch.Tensor`):
|
| 484 |
+
Query state with padding. Shape: (batch_size, query_length, num_heads, head_dim).
|
| 485 |
+
key (`torch.Tensor`):
|
| 486 |
+
Key state with padding. Shape: (batch_size, kv_seq_len, num_key_value_heads, head_dim).
|
| 487 |
+
value (`torch.Tensor`):
|
| 488 |
+
Value state with padding. Shape: (batch_size, kv_seq_len, num_key_value_heads, head_dim).
|
| 489 |
+
position_ids (`torch.Tensor`):
|
| 490 |
+
Boolean or int tensor of shape (batch_size, sequence_length), 1 means valid and 0 means not valid.
|
| 491 |
+
|
| 492 |
+
Return:
|
| 493 |
+
query (`torch.Tensor`):
|
| 494 |
+
Query state without padding. Shape: (total_target_length, num_heads, head_dim).
|
| 495 |
+
key (`torch.Tensor`):
|
| 496 |
+
Key state with padding. Shape: (total_source_length, num_key_value_heads, head_dim).
|
| 497 |
+
value (`torch.Tensor`):
|
| 498 |
+
Value state with padding. Shape: (total_source_length, num_key_value_heads, head_dim).
|
| 499 |
+
(cu_seqlens_q, cu_seqlens_k) (`tuple[int]`):
|
| 500 |
+
The cumulative sequence lengths for the target (query) and source (key, value), used to index into ragged (unpadded) tensors. `cu_seqlens` shape is (batch_size + 1,).
|
| 501 |
+
(max_seqlen_in_batch_q, max_seqlen_in_batch_k) (`tuple[int]`):
|
| 502 |
+
Maximum sequence length in batch (`max_seqlen_in_batch_q` for the target sequence i.e. query, `max_seqlen_in_batch_k` for the source sequence i.e. key/value).
|
| 503 |
+
"""
|
| 504 |
+
query = query.contiguous().view(-1, query.size(-2), query.size(-1))
|
| 505 |
+
key = key.contiguous().view(-1, key.size(-2), key.size(-1))
|
| 506 |
+
value = value.contiguous().view(-1, value.size(-2), value.size(-1))
|
| 507 |
+
|
| 508 |
+
(cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k) = prepare_fa_kwargs_from_position_ids(position_ids)
|
| 509 |
+
|
| 510 |
+
return (query, key, value, (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k))
|
| 511 |
+
|
| 512 |
+
|
| 513 |
+
def _is_packed_sequence(position_ids, batch_size):
|
| 514 |
+
"""
|
| 515 |
+
Check the position ids whether packed sequences are indicated or not
|
| 516 |
+
1. Position ids exist
|
| 517 |
+
2. Flattened sequences only are supported
|
| 518 |
+
3. Compile-friendly `not (torch.diff(position_ids, dim=-1) >= 0).all()`, i.e. we have multiple increasing sequences
|
| 519 |
+
"""
|
| 520 |
+
if position_ids is None:
|
| 521 |
+
return False
|
| 522 |
+
|
| 523 |
+
increasing_position_sequences = (
|
| 524 |
+
torch.arange(position_ids.shape[1], device=position_ids.device) + position_ids.min()
|
| 525 |
+
)
|
| 526 |
+
return batch_size == 1 and (increasing_position_sequences - position_ids).abs().sum().bool()
|
| 527 |
+
|
| 528 |
+
|
| 529 |
+
def fa_peft_integration_check(
|
| 530 |
+
q: torch.Tensor,
|
| 531 |
+
k: torch.Tensor,
|
| 532 |
+
v: torch.Tensor,
|
| 533 |
+
target_dtype: torch.dtype | None = None,
|
| 534 |
+
):
|
| 535 |
+
"""
|
| 536 |
+
PEFT usually casts the layer norms in float32 for training stability reasons
|
| 537 |
+
therefore the input hidden states gets silently casted in float32. Hence, we need
|
| 538 |
+
cast them back in float16 / bfloat16 just to be sure everything works as expected.
|
| 539 |
+
This might slowdown training & inference so it is recommended to not cast the LayerNorms!
|
| 540 |
+
"""
|
| 541 |
+
if target_dtype and q.dtype == torch.float32:
|
| 542 |
+
logger.warning_once(f"Casting fp32 inputs back to {target_dtype} for flash-attn compatibility.")
|
| 543 |
+
q, k, v = q.to(target_dtype), k.to(target_dtype), v.to(target_dtype)
|
| 544 |
+
return q, k, v
|
| 545 |
+
|
| 546 |
+
|
| 547 |
+
class FlashAttentionKwargs(TypedDict, total=False):
|
| 548 |
+
"""
|
| 549 |
+
Keyword arguments for Flash Attention with Compile.
|
| 550 |
+
|
| 551 |
+
Attributes:
|
| 552 |
+
cu_seq_lens_q (`torch.LongTensor`, *optional*)
|
| 553 |
+
Gets cumulative sequence length for query state.
|
| 554 |
+
cu_seq_lens_k (`torch.LongTensor`, *optional*)
|
| 555 |
+
Gets cumulative sequence length for key state.
|
| 556 |
+
max_length_q (`int`, *optional*):
|
| 557 |
+
Maximum sequence length for query state.
|
| 558 |
+
max_length_k (`int`, *optional*):
|
| 559 |
+
Maximum sequence length for key state.
|
| 560 |
+
"""
|
| 561 |
+
|
| 562 |
+
cu_seq_lens_q: torch.LongTensor | None
|
| 563 |
+
cu_seq_lens_k: torch.LongTensor | None
|
| 564 |
+
max_length_q: int | None
|
| 565 |
+
max_length_k: int | None
|
| 566 |
+
|
| 567 |
+
|
| 568 |
+
def _process_flash_attention_kwargs(
|
| 569 |
+
query_length: int,
|
| 570 |
+
key_length: int,
|
| 571 |
+
is_causal: bool,
|
| 572 |
+
dropout: float = 0.0,
|
| 573 |
+
softmax_scale: float | None = None,
|
| 574 |
+
sliding_window: int | None = None,
|
| 575 |
+
use_top_left_mask: bool = False,
|
| 576 |
+
softcap: float | None = None,
|
| 577 |
+
deterministic: bool | None = None,
|
| 578 |
+
s_aux: torch.Tensor | None = None,
|
| 579 |
+
max_seqlen_q: int | torch.IntTensor | None = None,
|
| 580 |
+
max_seqlen_k: int | torch.IntTensor | None = None,
|
| 581 |
+
supports_mapping: dict[str, bool] | None = None,
|
| 582 |
+
**kwargs,
|
| 583 |
+
):
|
| 584 |
+
"""
|
| 585 |
+
Returns a set of kwargs that are passed down to the according flash attention function based on
|
| 586 |
+
requested features and whether it is supported - depends on the version and kernel implementation
|
| 587 |
+
which is dynamically configured at `lazy_import_flash_attention`. The (un)supported features can be
|
| 588 |
+
inspected in `supports_mapping`, see `_lazy_define_process_function` for more details.
|
| 589 |
+
|
| 590 |
+
Args:
|
| 591 |
+
query_length (`int`):
|
| 592 |
+
Length of the query states
|
| 593 |
+
key_length (`int`):
|
| 594 |
+
Length of the key states
|
| 595 |
+
is_causal (`bool`):
|
| 596 |
+
Whether we perform causal (decoder) attention or full attention.
|
| 597 |
+
dropout (`float`):
|
| 598 |
+
Attention dropout.
|
| 599 |
+
softmax_scale (`float`, *optional*):
|
| 600 |
+
The scaling of QK^T before applying softmax. Default to `1 / sqrt(head_dim)`.
|
| 601 |
+
sliding_window (`int`, *optional*):
|
| 602 |
+
The size of the sliding window, i.e. we look at a max of `sliding_window` tokens back.
|
| 603 |
+
use_top_left_mask (`bool`):
|
| 604 |
+
Deprecated behavior of older versions of flash attention requiring different masking.
|
| 605 |
+
softcap (`float`, *optional*):
|
| 606 |
+
Softcap for the attention logits, used e.g. in gemma2.
|
| 607 |
+
deterministic (`bool`, *optional*):
|
| 608 |
+
Determines if the deterministic option introduced in flash_attn>=2.4.1 is enabled.
|
| 609 |
+
s_aux (`torch.Tensor`, *optional*):
|
| 610 |
+
Attention sink auxiliary that adds a `bias` to the attention calculation via an additional head.
|
| 611 |
+
max_seqlen_q (`Union[int, torch.IntTensor]`, *optional*):
|
| 612 |
+
The maximum sequence length in the query tensor during a varlen forward.
|
| 613 |
+
max_seqlen_k (`Union[int, torch.IntTensor]`, *optional*):
|
| 614 |
+
The maximum sequence length in the key/value tensor during a varlen forward.
|
| 615 |
+
Return:
|
| 616 |
+
flash_kwargs (`dict`):
|
| 617 |
+
A dict of kwargs that are requested and supported.
|
| 618 |
+
"""
|
| 619 |
+
flash_kwargs = {
|
| 620 |
+
"causal": is_causal and not (use_top_left_mask and query_length == 1),
|
| 621 |
+
"softmax_scale": softmax_scale,
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
if supports_mapping["dropout_p"]:
|
| 625 |
+
flash_kwargs["dropout_p"] = dropout
|
| 626 |
+
|
| 627 |
+
if supports_mapping["window_size"] and sliding_window is not None and key_length > sliding_window:
|
| 628 |
+
# The flash attention API sets inclusive boundaries, i.e. (4, 0) would take 4 tokens to the left
|
| 629 |
+
# and the current token for a total size of 5. However, we usually define our window sizes by
|
| 630 |
+
# their total window size (when causal). Encoder models as of now seldom use SWA and when they
|
| 631 |
+
# do, they must align with this symmetric logic, i.e. for a total of `2*sliding_window + 1`.
|
| 632 |
+
flash_kwargs["window_size"] = (sliding_window - 1, sliding_window - 1)
|
| 633 |
+
|
| 634 |
+
if supports_mapping["deterministic"]:
|
| 635 |
+
flash_kwargs["deterministic"] = (
|
| 636 |
+
deterministic if deterministic is not None else os.getenv("FLASH_ATTENTION_DETERMINISTIC", "0") == "1"
|
| 637 |
+
)
|
| 638 |
+
|
| 639 |
+
if supports_mapping["softcap"] and softcap is not None:
|
| 640 |
+
flash_kwargs["softcap"] = softcap
|
| 641 |
+
|
| 642 |
+
if ((legacy_sink_param := supports_mapping["s_aux"]) or supports_mapping["learnable_sink"]) and s_aux is not None:
|
| 643 |
+
if legacy_sink_param:
|
| 644 |
+
flash_kwargs["s_aux"] = s_aux # e.g. FA3 (vllm)
|
| 645 |
+
else:
|
| 646 |
+
flash_kwargs["learnable_sink"] = s_aux # FA4
|
| 647 |
+
|
| 648 |
+
# There is a limitation of the flash attention API, as the function `flash_attn_varlen_func`
|
| 649 |
+
# may require `max_length_q`, `max_length_k` to be passed as `int` and not `torch.Tensor`.
|
| 650 |
+
#
|
| 651 |
+
# You can either set
|
| 652 |
+
# - Env: `TORCHDYNAMO_CAPTURE_SCALAR_OUTPUTS=1`
|
| 653 |
+
# - Before compiling: `torch._dynamo.config.capture_scalar_outputs = True`
|
| 654 |
+
# to allow torch compile to handle scalar outputs in those cases.
|
| 655 |
+
same_max_seqlen = max_seqlen_q is max_seqlen_k # to avoid 2x device syncs
|
| 656 |
+
if supports_mapping["max_seqlen_q"] and max_seqlen_q is not None:
|
| 657 |
+
if not isinstance(max_seqlen_q, int) and is_tracing(max_seqlen_q):
|
| 658 |
+
max_seqlen_q = max_seqlen_q.item()
|
| 659 |
+
flash_kwargs["max_seqlen_q"] = max_seqlen_q
|
| 660 |
+
|
| 661 |
+
if supports_mapping["max_seqlen_k"] and max_seqlen_k is not None:
|
| 662 |
+
if same_max_seqlen and flash_kwargs["max_seqlen_q"] is not None:
|
| 663 |
+
max_seqlen_k = flash_kwargs["max_seqlen_q"]
|
| 664 |
+
elif not isinstance(max_seqlen_k, int) and is_tracing(max_seqlen_k):
|
| 665 |
+
max_seqlen_k = max_seqlen_k.item()
|
| 666 |
+
flash_kwargs["max_seqlen_k"] = max_seqlen_k
|
| 667 |
+
|
| 668 |
+
return flash_kwargs
|
| 669 |
+
|
| 670 |
+
|
| 671 |
+
def _flash_attention_forward(
|
| 672 |
+
query_states: torch.Tensor,
|
| 673 |
+
key_states: torch.Tensor,
|
| 674 |
+
value_states: torch.Tensor,
|
| 675 |
+
attention_mask: torch.Tensor | None,
|
| 676 |
+
query_length: int,
|
| 677 |
+
is_causal: bool,
|
| 678 |
+
dropout: float = 0.0,
|
| 679 |
+
position_ids: torch.Tensor | None = None,
|
| 680 |
+
softmax_scale: float | None = None,
|
| 681 |
+
sliding_window: int | None = None,
|
| 682 |
+
use_top_left_mask: bool = False,
|
| 683 |
+
softcap: float | None = None,
|
| 684 |
+
deterministic: bool | None = None,
|
| 685 |
+
cu_seq_lens_q: torch.LongTensor | None = None,
|
| 686 |
+
cu_seq_lens_k: torch.LongTensor | None = None,
|
| 687 |
+
max_length_q: int | None = None,
|
| 688 |
+
max_length_k: int | None = None,
|
| 689 |
+
target_dtype: torch.dtype | None = None,
|
| 690 |
+
attn_implementation: str | None = None,
|
| 691 |
+
**kwargs,
|
| 692 |
+
):
|
| 693 |
+
"""
|
| 694 |
+
Calls the forward method of Flash Attention - if the input hidden states contain at least one padding token
|
| 695 |
+
first unpad the input, then computes the attention scores and pad the final attention scores.
|
| 696 |
+
|
| 697 |
+
(Optional) kwargs are described further in `_process_flash_attention_kwargs` and `FlashAttentionKwargs`.
|
| 698 |
+
|
| 699 |
+
Args:
|
| 700 |
+
query_states (`torch.Tensor`):
|
| 701 |
+
Input query states to be passed to Flash Attention API
|
| 702 |
+
key_states (`torch.Tensor`):
|
| 703 |
+
Input key states to be passed to Flash Attention API
|
| 704 |
+
value_states (`torch.Tensor`):
|
| 705 |
+
Input value states to be passed to Flash Attention API
|
| 706 |
+
attention_mask (`torch.Tensor`, *optional*):
|
| 707 |
+
The padding mask - corresponds to a tensor of size `(batch_size, seq_len)` where 0 stands for the
|
| 708 |
+
position of padding tokens and 1 for the position of non-padding tokens.
|
| 709 |
+
attn_implementation (`str`, *optional*):
|
| 710 |
+
The attention implementation to use. If None, will default to the one based on the environment.
|
| 711 |
+
"""
|
| 712 |
+
(flash_fn, flash_varlen_fn, _, pad_fn, unpad_fn), process_flash_kwargs_fn = lazy_import_flash_attention(
|
| 713 |
+
attn_implementation
|
| 714 |
+
)
|
| 715 |
+
|
| 716 |
+
# PEFT possibly silently casts tensors to fp32, this potentially reconverts to correct dtype or is a no op
|
| 717 |
+
query_states, key_states, value_states = fa_peft_integration_check(
|
| 718 |
+
query_states, key_states, value_states, target_dtype
|
| 719 |
+
)
|
| 720 |
+
|
| 721 |
+
# Extract the flash attention kwargs that have been requested (and are supported by the implementation)
|
| 722 |
+
flash_kwargs = partial(
|
| 723 |
+
process_flash_kwargs_fn,
|
| 724 |
+
query_length=query_length,
|
| 725 |
+
key_length=key_states.size(1),
|
| 726 |
+
is_causal=is_causal,
|
| 727 |
+
dropout=dropout,
|
| 728 |
+
softmax_scale=softmax_scale,
|
| 729 |
+
sliding_window=sliding_window,
|
| 730 |
+
use_top_left_mask=use_top_left_mask,
|
| 731 |
+
softcap=softcap,
|
| 732 |
+
deterministic=deterministic,
|
| 733 |
+
**kwargs,
|
| 734 |
+
)
|
| 735 |
+
|
| 736 |
+
# We will use `flash_varlen_fn` to prevent cross-example attention and also allow padding free approach under two cases:
|
| 737 |
+
# Case 1. If position ids is provided and the position ids indicate packed sequences, see `_is_packed_sequence`.
|
| 738 |
+
# Case 2. Some models pass directly pre-computed `cu_seqlens` so we don't need to infer it from position ids. It is safe to
|
| 739 |
+
# use `flash_varlen_fn` knowing we already have all necessary the kwargs.
|
| 740 |
+
#
|
| 741 |
+
# NOTE: it is user's responsibility to take care of flattening `position_ids` if that's needed by the model.
|
| 742 |
+
# See #39121 for more information.
|
| 743 |
+
is_fa_with_position_ids = _is_packed_sequence(position_ids, batch_size=query_states.size(0))
|
| 744 |
+
is_fa_with_varlen_kwargs = all(
|
| 745 |
+
kwarg is not None for kwarg in (cu_seq_lens_q, cu_seq_lens_k, max_length_q, max_length_k)
|
| 746 |
+
)
|
| 747 |
+
|
| 748 |
+
# Contains at least one padding token in the sequence
|
| 749 |
+
if attention_mask is not None:
|
| 750 |
+
q, k, v, indices_q, (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k) = _upad_input(
|
| 751 |
+
query_states, key_states, value_states, attention_mask, query_length, unpad_fn
|
| 752 |
+
)
|
| 753 |
+
|
| 754 |
+
# TODO for now this is required to work with
|
| 755 |
+
# https://huggingface.co/kernels-community/metal-flash-sdpa/blob/main/torch-ext/metal_flash_sdpa/__init__.py
|
| 756 |
+
if "mps" in str(q.device):
|
| 757 |
+
cu_seq_lens_k = cu_seq_lens_k.clone()
|
| 758 |
+
|
| 759 |
+
out_unpad = flash_varlen_fn(
|
| 760 |
+
q,
|
| 761 |
+
k,
|
| 762 |
+
v,
|
| 763 |
+
cu_seqlens_q=cu_seq_lens_q,
|
| 764 |
+
cu_seqlens_k=cu_seq_lens_k,
|
| 765 |
+
**flash_kwargs(max_seqlen_q=max_length_q, max_seqlen_k=max_length_k),
|
| 766 |
+
)
|
| 767 |
+
if isinstance(out_unpad, tuple):
|
| 768 |
+
out_unpad = out_unpad[0]
|
| 769 |
+
|
| 770 |
+
out = pad_fn(out_unpad, indices_q, query_states.size(0), query_length)
|
| 771 |
+
|
| 772 |
+
# Padding free, i.e. sequences flattened into one total sequence
|
| 773 |
+
elif is_fa_with_varlen_kwargs or is_fa_with_position_ids:
|
| 774 |
+
if cu_seq_lens_q is None or cu_seq_lens_k is None:
|
| 775 |
+
q, k, v, (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k) = _prepare_from_posids(
|
| 776 |
+
query_states, key_states, value_states, position_ids
|
| 777 |
+
)
|
| 778 |
+
else:
|
| 779 |
+
q = query_states.reshape(-1, query_states.size(-2), query_states.size(-1))
|
| 780 |
+
k = key_states.reshape(-1, key_states.size(-2), key_states.size(-1))
|
| 781 |
+
v = value_states.reshape(-1, value_states.size(-2), value_states.size(-1))
|
| 782 |
+
|
| 783 |
+
# TODO for now this is required to work with
|
| 784 |
+
# https://huggingface.co/kernels-community/metal-flash-sdpa/blob/main/torch-ext/metal_flash_sdpa/__init__.py
|
| 785 |
+
if "mps" in str(q.device):
|
| 786 |
+
cu_seq_lens_k = cu_seq_lens_k.clone()
|
| 787 |
+
|
| 788 |
+
out = flash_varlen_fn(
|
| 789 |
+
q,
|
| 790 |
+
k,
|
| 791 |
+
v,
|
| 792 |
+
cu_seqlens_q=cu_seq_lens_q,
|
| 793 |
+
cu_seqlens_k=cu_seq_lens_k,
|
| 794 |
+
**flash_kwargs(max_seqlen_q=max_length_q, max_seqlen_k=max_length_k),
|
| 795 |
+
)
|
| 796 |
+
if isinstance(out, tuple):
|
| 797 |
+
out = out[0]
|
| 798 |
+
|
| 799 |
+
out = out.view(query_states.size(0), -1, out.size(-2), out.size(-1))
|
| 800 |
+
|
| 801 |
+
# No padding
|
| 802 |
+
else:
|
| 803 |
+
out = flash_fn(query_states, key_states, value_states, **flash_kwargs())
|
| 804 |
+
if isinstance(out, tuple):
|
| 805 |
+
out = out[0]
|
| 806 |
+
|
| 807 |
+
return out
|
third_party/transformers/src/transformers/modeling_layers.py
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from functools import partial
|
| 15 |
+
|
| 16 |
+
import torch
|
| 17 |
+
import torch.nn as nn
|
| 18 |
+
|
| 19 |
+
from .cache_utils import Cache
|
| 20 |
+
from .modeling_outputs import (
|
| 21 |
+
BaseModelOutputWithPast,
|
| 22 |
+
QuestionAnsweringModelOutput,
|
| 23 |
+
SequenceClassifierOutputWithPast,
|
| 24 |
+
TokenClassifierOutput,
|
| 25 |
+
)
|
| 26 |
+
from .models.auto import AutoModel
|
| 27 |
+
from .processing_utils import Unpack
|
| 28 |
+
from .utils import TransformersKwargs, auto_docstring, can_return_tuple, logging
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
logger = logging.get_logger(__name__)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class GradientCheckpointingLayer(nn.Module):
|
| 35 |
+
"""Base class for layers with gradient checkpointing.
|
| 36 |
+
|
| 37 |
+
This class enables gradient checkpointing functionality for a layer. By default, gradient checkpointing is disabled
|
| 38 |
+
(`gradient_checkpointing = False`). When `model.set_gradient_checkpointing()` is called, gradient checkpointing is
|
| 39 |
+
enabled by setting `gradient_checkpointing = True` and assigning a checkpointing function to `_gradient_checkpointing_func`.
|
| 40 |
+
|
| 41 |
+
Important:
|
| 42 |
+
|
| 43 |
+
When using gradient checkpointing with `use_reentrant=True`, inputs that require gradients (e.g. hidden states)
|
| 44 |
+
must be passed as positional arguments (`*args`) rather than keyword arguments to properly propagate gradients.
|
| 45 |
+
|
| 46 |
+
Example:
|
| 47 |
+
|
| 48 |
+
```python
|
| 49 |
+
>>> # Correct - hidden_states passed as positional arg
|
| 50 |
+
>>> out = self.layer(hidden_states, attention_mask=attention_mask)
|
| 51 |
+
|
| 52 |
+
>>> # Incorrect - hidden_states passed as keyword arg
|
| 53 |
+
>>> out = self.layer(hidden_states=hidden_states, attention_mask=attention_mask)
|
| 54 |
+
```
|
| 55 |
+
"""
|
| 56 |
+
|
| 57 |
+
gradient_checkpointing = False
|
| 58 |
+
|
| 59 |
+
def __call__(self, *args, **kwargs):
|
| 60 |
+
if self.gradient_checkpointing and self.training:
|
| 61 |
+
do_warn = False
|
| 62 |
+
layer_name = self.__class__.__name__
|
| 63 |
+
message = f"Caching is incompatible with gradient checkpointing in {layer_name}. Setting"
|
| 64 |
+
|
| 65 |
+
if "use_cache" in kwargs and kwargs["use_cache"]:
|
| 66 |
+
kwargs["use_cache"] = False
|
| 67 |
+
message += " `use_cache=False`,"
|
| 68 |
+
do_warn = True
|
| 69 |
+
|
| 70 |
+
# different names for the same thing in different layers
|
| 71 |
+
# TODO cyril: this one without `S` can be removed after deprecation cycle
|
| 72 |
+
if "past_key_value" in kwargs and kwargs["past_key_value"] is not None:
|
| 73 |
+
kwargs["past_key_value"] = None
|
| 74 |
+
message += " `past_key_value=None`,"
|
| 75 |
+
do_warn = True
|
| 76 |
+
|
| 77 |
+
if "past_key_values" in kwargs and kwargs["past_key_values"] is not None:
|
| 78 |
+
kwargs["past_key_values"] = None
|
| 79 |
+
message += " `past_key_values=None`,"
|
| 80 |
+
do_warn = True
|
| 81 |
+
|
| 82 |
+
if "layer_past" in kwargs and kwargs["layer_past"] is not None:
|
| 83 |
+
kwargs["layer_past"] = None
|
| 84 |
+
message += " `layer_past=None`,"
|
| 85 |
+
do_warn = True
|
| 86 |
+
|
| 87 |
+
# warn if anything was changed
|
| 88 |
+
if do_warn:
|
| 89 |
+
message = message.rstrip(",") + "."
|
| 90 |
+
logger.warning_once(message)
|
| 91 |
+
|
| 92 |
+
return self._gradient_checkpointing_func(partial(super().__call__, **kwargs), *args)
|
| 93 |
+
return super().__call__(*args, **kwargs)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
@auto_docstring
|
| 97 |
+
class GenericForSequenceClassification:
|
| 98 |
+
base_model_prefix = "model"
|
| 99 |
+
|
| 100 |
+
def __init__(self, config):
|
| 101 |
+
super().__init__(config)
|
| 102 |
+
self.num_labels = config.num_labels
|
| 103 |
+
# Similar to `self.model = AutoModel.from_config(config)` but allows to change the base model name if needed in the child class
|
| 104 |
+
setattr(self, self.base_model_prefix, AutoModel.from_config(config))
|
| 105 |
+
self.score = nn.Linear(config.hidden_size, self.num_labels, bias=False)
|
| 106 |
+
|
| 107 |
+
# Initialize weights and apply final processing
|
| 108 |
+
self.post_init()
|
| 109 |
+
|
| 110 |
+
@can_return_tuple
|
| 111 |
+
@auto_docstring
|
| 112 |
+
def forward(
|
| 113 |
+
self,
|
| 114 |
+
input_ids: torch.LongTensor | None = None,
|
| 115 |
+
attention_mask: torch.Tensor | None = None,
|
| 116 |
+
position_ids: torch.LongTensor | None = None,
|
| 117 |
+
past_key_values: Cache | None = None,
|
| 118 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 119 |
+
labels: torch.LongTensor | None = None,
|
| 120 |
+
use_cache: bool | None = None,
|
| 121 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 122 |
+
) -> SequenceClassifierOutputWithPast:
|
| 123 |
+
transformer_outputs: BaseModelOutputWithPast = getattr(self, self.base_model_prefix)(
|
| 124 |
+
input_ids,
|
| 125 |
+
attention_mask=attention_mask,
|
| 126 |
+
position_ids=position_ids,
|
| 127 |
+
past_key_values=past_key_values,
|
| 128 |
+
inputs_embeds=inputs_embeds,
|
| 129 |
+
use_cache=use_cache,
|
| 130 |
+
**kwargs,
|
| 131 |
+
)
|
| 132 |
+
hidden_states = transformer_outputs.last_hidden_state
|
| 133 |
+
logits = self.score(hidden_states)
|
| 134 |
+
|
| 135 |
+
if input_ids is not None:
|
| 136 |
+
batch_size = input_ids.shape[0]
|
| 137 |
+
else:
|
| 138 |
+
batch_size = inputs_embeds.shape[0]
|
| 139 |
+
|
| 140 |
+
if self.config.pad_token_id is None and batch_size != 1:
|
| 141 |
+
raise ValueError("Cannot handle batch sizes > 1 if no padding token is defined.")
|
| 142 |
+
if self.config.pad_token_id is None:
|
| 143 |
+
last_non_pad_token = -1
|
| 144 |
+
elif input_ids is not None:
|
| 145 |
+
# To handle both left- and right- padding, we take the rightmost token that is not equal to pad_token_id
|
| 146 |
+
non_pad_mask = (input_ids != self.config.pad_token_id).to(logits.device, torch.int32)
|
| 147 |
+
token_indices = torch.arange(input_ids.shape[-1], device=logits.device, dtype=torch.int32)
|
| 148 |
+
last_non_pad_token = (token_indices * non_pad_mask).argmax(-1)
|
| 149 |
+
else:
|
| 150 |
+
last_non_pad_token = -1
|
| 151 |
+
logger.warning_once(
|
| 152 |
+
f"{self.__class__.__name__} will not detect padding tokens in `inputs_embeds`. Results may be "
|
| 153 |
+
"unexpected if using padding tokens in conjunction with `inputs_embeds.`"
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
pooled_logits = logits[torch.arange(batch_size, device=logits.device), last_non_pad_token]
|
| 157 |
+
|
| 158 |
+
loss = None
|
| 159 |
+
if labels is not None:
|
| 160 |
+
loss = self.loss_function(logits=logits, labels=labels, pooled_logits=pooled_logits, config=self.config)
|
| 161 |
+
|
| 162 |
+
return SequenceClassifierOutputWithPast(
|
| 163 |
+
loss=loss,
|
| 164 |
+
logits=pooled_logits,
|
| 165 |
+
past_key_values=transformer_outputs.past_key_values,
|
| 166 |
+
hidden_states=transformer_outputs.hidden_states,
|
| 167 |
+
attentions=transformer_outputs.attentions,
|
| 168 |
+
)
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
@auto_docstring
|
| 172 |
+
class GenericForQuestionAnswering:
|
| 173 |
+
base_model_prefix = "model"
|
| 174 |
+
|
| 175 |
+
def __init__(self, config):
|
| 176 |
+
super().__init__(config)
|
| 177 |
+
# Similar to `self.model = AutoModel.from_config(config)` but allows to change the base model name if needed in the child class
|
| 178 |
+
setattr(self, self.base_model_prefix, AutoModel.from_config(config))
|
| 179 |
+
self.qa_outputs = nn.Linear(config.hidden_size, 2)
|
| 180 |
+
|
| 181 |
+
# Initialize weights and apply final processing
|
| 182 |
+
self.post_init()
|
| 183 |
+
|
| 184 |
+
def get_input_embeddings(self):
|
| 185 |
+
return getattr(self, self.base_model_prefix).embed_tokens
|
| 186 |
+
|
| 187 |
+
def set_input_embeddings(self, value):
|
| 188 |
+
getattr(self, self.base_model_prefix).embed_tokens = value
|
| 189 |
+
|
| 190 |
+
@can_return_tuple
|
| 191 |
+
@auto_docstring
|
| 192 |
+
def forward(
|
| 193 |
+
self,
|
| 194 |
+
input_ids: torch.LongTensor | None = None,
|
| 195 |
+
attention_mask: torch.Tensor | None = None,
|
| 196 |
+
position_ids: torch.LongTensor | None = None,
|
| 197 |
+
past_key_values: Cache | None = None,
|
| 198 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 199 |
+
start_positions: torch.LongTensor | None = None,
|
| 200 |
+
end_positions: torch.LongTensor | None = None,
|
| 201 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 202 |
+
) -> QuestionAnsweringModelOutput:
|
| 203 |
+
outputs: BaseModelOutputWithPast = getattr(self, self.base_model_prefix)(
|
| 204 |
+
input_ids,
|
| 205 |
+
attention_mask=attention_mask,
|
| 206 |
+
position_ids=position_ids,
|
| 207 |
+
past_key_values=past_key_values,
|
| 208 |
+
inputs_embeds=inputs_embeds,
|
| 209 |
+
**kwargs,
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
sequence_output = outputs.last_hidden_state
|
| 213 |
+
|
| 214 |
+
logits = self.qa_outputs(sequence_output)
|
| 215 |
+
start_logits, end_logits = logits.split(1, dim=-1)
|
| 216 |
+
start_logits = start_logits.squeeze(-1).contiguous()
|
| 217 |
+
end_logits = end_logits.squeeze(-1).contiguous()
|
| 218 |
+
|
| 219 |
+
loss = None
|
| 220 |
+
if start_positions is not None and end_positions is not None:
|
| 221 |
+
loss = self.loss_function(start_logits, end_logits, start_positions, end_positions, **kwargs)
|
| 222 |
+
|
| 223 |
+
return QuestionAnsweringModelOutput(
|
| 224 |
+
loss=loss,
|
| 225 |
+
start_logits=start_logits,
|
| 226 |
+
end_logits=end_logits,
|
| 227 |
+
hidden_states=outputs.hidden_states,
|
| 228 |
+
attentions=outputs.attentions,
|
| 229 |
+
)
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
@auto_docstring
|
| 233 |
+
class GenericForTokenClassification:
|
| 234 |
+
base_model_prefix = "model"
|
| 235 |
+
|
| 236 |
+
def __init__(self, config):
|
| 237 |
+
super().__init__(config)
|
| 238 |
+
self.num_labels = config.num_labels
|
| 239 |
+
# Similar to `self.model = AutoModel.from_config(config)` but allows to change the base model name if needed in the child class
|
| 240 |
+
setattr(self, self.base_model_prefix, AutoModel.from_config(config))
|
| 241 |
+
if getattr(config, "classifier_dropout", None) is not None:
|
| 242 |
+
classifier_dropout = config.classifier_dropout
|
| 243 |
+
elif getattr(config, "hidden_dropout", None) is not None:
|
| 244 |
+
classifier_dropout = config.hidden_dropout
|
| 245 |
+
else:
|
| 246 |
+
classifier_dropout = 0.1
|
| 247 |
+
self.dropout = nn.Dropout(classifier_dropout)
|
| 248 |
+
self.score = nn.Linear(config.hidden_size, config.num_labels)
|
| 249 |
+
|
| 250 |
+
# Initialize weights and apply final processing
|
| 251 |
+
self.post_init()
|
| 252 |
+
|
| 253 |
+
@can_return_tuple
|
| 254 |
+
@auto_docstring
|
| 255 |
+
def forward(
|
| 256 |
+
self,
|
| 257 |
+
input_ids: torch.LongTensor | None = None,
|
| 258 |
+
attention_mask: torch.Tensor | None = None,
|
| 259 |
+
position_ids: torch.LongTensor | None = None,
|
| 260 |
+
past_key_values: Cache | None = None,
|
| 261 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 262 |
+
labels: torch.LongTensor | None = None,
|
| 263 |
+
use_cache: bool | None = None,
|
| 264 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 265 |
+
) -> TokenClassifierOutput:
|
| 266 |
+
outputs: BaseModelOutputWithPast = getattr(self, self.base_model_prefix)(
|
| 267 |
+
input_ids,
|
| 268 |
+
attention_mask=attention_mask,
|
| 269 |
+
position_ids=position_ids,
|
| 270 |
+
past_key_values=past_key_values,
|
| 271 |
+
inputs_embeds=inputs_embeds,
|
| 272 |
+
use_cache=use_cache,
|
| 273 |
+
**kwargs,
|
| 274 |
+
)
|
| 275 |
+
sequence_output = outputs.last_hidden_state
|
| 276 |
+
sequence_output = self.dropout(sequence_output)
|
| 277 |
+
logits = self.score(sequence_output)
|
| 278 |
+
|
| 279 |
+
loss = None
|
| 280 |
+
if labels is not None:
|
| 281 |
+
loss = self.loss_function(logits, labels, self.config)
|
| 282 |
+
|
| 283 |
+
return TokenClassifierOutput(
|
| 284 |
+
loss=loss,
|
| 285 |
+
logits=logits,
|
| 286 |
+
hidden_states=outputs.hidden_states,
|
| 287 |
+
attentions=outputs.attentions,
|
| 288 |
+
)
|
third_party/transformers/src/transformers/models/__init__.py
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
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 .afmoe import *
|
| 22 |
+
from .aimv2 import *
|
| 23 |
+
from .albert import *
|
| 24 |
+
from .align import *
|
| 25 |
+
from .altclip import *
|
| 26 |
+
from .apertus import *
|
| 27 |
+
from .arcee import *
|
| 28 |
+
from .aria import *
|
| 29 |
+
from .audio_spectrogram_transformer import *
|
| 30 |
+
from .audioflamingo3 import *
|
| 31 |
+
from .auto import *
|
| 32 |
+
from .autoformer import *
|
| 33 |
+
from .aya_vision import *
|
| 34 |
+
from .bamba import *
|
| 35 |
+
from .bark import *
|
| 36 |
+
from .bart import *
|
| 37 |
+
from .barthez import *
|
| 38 |
+
from .bartpho import *
|
| 39 |
+
from .beit import *
|
| 40 |
+
from .bert import *
|
| 41 |
+
from .bert_generation import *
|
| 42 |
+
from .bert_japanese import *
|
| 43 |
+
from .bertweet import *
|
| 44 |
+
from .big_bird import *
|
| 45 |
+
from .bigbird_pegasus import *
|
| 46 |
+
from .biogpt import *
|
| 47 |
+
from .bit import *
|
| 48 |
+
from .bitnet import *
|
| 49 |
+
from .blenderbot import *
|
| 50 |
+
from .blenderbot_small import *
|
| 51 |
+
from .blip import *
|
| 52 |
+
from .blip_2 import *
|
| 53 |
+
from .bloom import *
|
| 54 |
+
from .blt import *
|
| 55 |
+
from .bridgetower import *
|
| 56 |
+
from .bros import *
|
| 57 |
+
from .byt5 import *
|
| 58 |
+
from .camembert import *
|
| 59 |
+
from .canine import *
|
| 60 |
+
from .chameleon import *
|
| 61 |
+
from .chinese_clip import *
|
| 62 |
+
from .chmv2 import *
|
| 63 |
+
from .clap import *
|
| 64 |
+
from .clip import *
|
| 65 |
+
from .clipseg import *
|
| 66 |
+
from .clvp import *
|
| 67 |
+
from .code_llama import *
|
| 68 |
+
from .codegen import *
|
| 69 |
+
from .cohere import *
|
| 70 |
+
from .cohere2 import *
|
| 71 |
+
from .cohere2_vision import *
|
| 72 |
+
from .cohere_asr import *
|
| 73 |
+
from .colmodernvbert import *
|
| 74 |
+
from .colpali import *
|
| 75 |
+
from .colqwen2 import *
|
| 76 |
+
from .conditional_detr import *
|
| 77 |
+
from .convbert import *
|
| 78 |
+
from .convnext import *
|
| 79 |
+
from .convnextv2 import *
|
| 80 |
+
from .cpm import *
|
| 81 |
+
from .cpmant import *
|
| 82 |
+
from .csm import *
|
| 83 |
+
from .ctrl import *
|
| 84 |
+
from .cvt import *
|
| 85 |
+
from .cwm import *
|
| 86 |
+
from .d_fine import *
|
| 87 |
+
from .dab_detr import *
|
| 88 |
+
from .dac import *
|
| 89 |
+
from .data2vec import *
|
| 90 |
+
from .dbrx import *
|
| 91 |
+
from .deberta import *
|
| 92 |
+
from .deberta_v2 import *
|
| 93 |
+
from .decision_transformer import *
|
| 94 |
+
from .deepseek_v2 import *
|
| 95 |
+
from .deepseek_v3 import *
|
| 96 |
+
from .deepseek_vl import *
|
| 97 |
+
from .deepseek_vl_hybrid import *
|
| 98 |
+
from .deformable_detr import *
|
| 99 |
+
from .deit import *
|
| 100 |
+
from .deprecated import *
|
| 101 |
+
from .depth_anything import *
|
| 102 |
+
from .depth_pro import *
|
| 103 |
+
from .detr import *
|
| 104 |
+
from .dia import *
|
| 105 |
+
from .dialogpt import *
|
| 106 |
+
from .diffllama import *
|
| 107 |
+
from .dinat import *
|
| 108 |
+
from .dinov2 import *
|
| 109 |
+
from .dinov2_with_registers import *
|
| 110 |
+
from .dinov3_convnext import *
|
| 111 |
+
from .dinov3_vit import *
|
| 112 |
+
from .distilbert import *
|
| 113 |
+
from .dit import *
|
| 114 |
+
from .doge import *
|
| 115 |
+
from .donut import *
|
| 116 |
+
from .dots1 import *
|
| 117 |
+
from .dpr import *
|
| 118 |
+
from .dpt import *
|
| 119 |
+
from .edgetam import *
|
| 120 |
+
from .edgetam_video import *
|
| 121 |
+
from .efficientloftr import *
|
| 122 |
+
from .efficientnet import *
|
| 123 |
+
from .electra import *
|
| 124 |
+
from .emu3 import *
|
| 125 |
+
from .encodec import *
|
| 126 |
+
from .encoder_decoder import *
|
| 127 |
+
from .eomt import *
|
| 128 |
+
from .eomt_dinov3 import *
|
| 129 |
+
from .ernie import *
|
| 130 |
+
from .ernie4_5 import *
|
| 131 |
+
from .ernie4_5_moe import *
|
| 132 |
+
from .ernie4_5_vl_moe import *
|
| 133 |
+
from .esm import *
|
| 134 |
+
from .evolla import *
|
| 135 |
+
from .exaone4 import *
|
| 136 |
+
from .exaone_moe import *
|
| 137 |
+
from .falcon import *
|
| 138 |
+
from .falcon_h1 import *
|
| 139 |
+
from .falcon_mamba import *
|
| 140 |
+
from .fast_vlm import *
|
| 141 |
+
from .fastspeech2_conformer import *
|
| 142 |
+
from .flaubert import *
|
| 143 |
+
from .flava import *
|
| 144 |
+
from .flex_olmo import *
|
| 145 |
+
from .florence2 import *
|
| 146 |
+
from .fnet import *
|
| 147 |
+
from .focalnet import *
|
| 148 |
+
from .fsmt import *
|
| 149 |
+
from .funnel import *
|
| 150 |
+
from .fuyu import *
|
| 151 |
+
from .gemma import *
|
| 152 |
+
from .gemma2 import *
|
| 153 |
+
from .gemma3 import *
|
| 154 |
+
from .gemma3n import *
|
| 155 |
+
from .gemma4 import *
|
| 156 |
+
from .git import *
|
| 157 |
+
from .glm import *
|
| 158 |
+
from .glm4 import *
|
| 159 |
+
from .glm4_moe import *
|
| 160 |
+
from .glm4_moe_lite import *
|
| 161 |
+
from .glm4v import *
|
| 162 |
+
from .glm4v_moe import *
|
| 163 |
+
from .glm46v import *
|
| 164 |
+
from .glm_image import *
|
| 165 |
+
from .glm_moe_dsa import *
|
| 166 |
+
from .glm_ocr import *
|
| 167 |
+
from .glmasr import *
|
| 168 |
+
from .glpn import *
|
| 169 |
+
from .got_ocr2 import *
|
| 170 |
+
from .gpt2 import *
|
| 171 |
+
from .gpt_bigcode import *
|
| 172 |
+
from .gpt_neo import *
|
| 173 |
+
from .gpt_neox import *
|
| 174 |
+
from .gpt_neox_japanese import *
|
| 175 |
+
from .gpt_oss import *
|
| 176 |
+
from .gpt_sw3 import *
|
| 177 |
+
from .gptj import *
|
| 178 |
+
from .granite import *
|
| 179 |
+
from .granite_speech import *
|
| 180 |
+
from .granitemoe import *
|
| 181 |
+
from .granitemoehybrid import *
|
| 182 |
+
from .granitemoeshared import *
|
| 183 |
+
from .grounding_dino import *
|
| 184 |
+
from .groupvit import *
|
| 185 |
+
from .helium import *
|
| 186 |
+
from .herbert import *
|
| 187 |
+
from .hgnet_v2 import *
|
| 188 |
+
from .hiera import *
|
| 189 |
+
from .higgs_audio_v2 import *
|
| 190 |
+
from .higgs_audio_v2_tokenizer import *
|
| 191 |
+
from .hubert import *
|
| 192 |
+
from .hunyuan_v1_dense import *
|
| 193 |
+
from .hunyuan_v1_moe import *
|
| 194 |
+
from .ibert import *
|
| 195 |
+
from .idefics import *
|
| 196 |
+
from .idefics2 import *
|
| 197 |
+
from .idefics3 import *
|
| 198 |
+
from .ijepa import *
|
| 199 |
+
from .imagegpt import *
|
| 200 |
+
from .informer import *
|
| 201 |
+
from .instructblip import *
|
| 202 |
+
from .instructblipvideo import *
|
| 203 |
+
from .internvl import *
|
| 204 |
+
from .jais2 import *
|
| 205 |
+
from .jamba import *
|
| 206 |
+
from .janus import *
|
| 207 |
+
from .jetmoe import *
|
| 208 |
+
from .jina_embeddings_v3 import *
|
| 209 |
+
from .kosmos2 import *
|
| 210 |
+
from .kosmos2_5 import *
|
| 211 |
+
from .kyutai_speech_to_text import *
|
| 212 |
+
from .lasr import *
|
| 213 |
+
from .layoutlm import *
|
| 214 |
+
from .layoutlmv2 import *
|
| 215 |
+
from .layoutlmv3 import *
|
| 216 |
+
from .layoutxlm import *
|
| 217 |
+
from .led import *
|
| 218 |
+
from .levit import *
|
| 219 |
+
from .lfm2 import *
|
| 220 |
+
from .lfm2_moe import *
|
| 221 |
+
from .lfm2_vl import *
|
| 222 |
+
from .lightglue import *
|
| 223 |
+
from .lilt import *
|
| 224 |
+
from .llama import *
|
| 225 |
+
from .llama4 import *
|
| 226 |
+
from .llava import *
|
| 227 |
+
from .llava_next import *
|
| 228 |
+
from .llava_next_video import *
|
| 229 |
+
from .llava_onevision import *
|
| 230 |
+
from .longcat_flash import *
|
| 231 |
+
from .longformer import *
|
| 232 |
+
from .longt5 import *
|
| 233 |
+
from .luke import *
|
| 234 |
+
from .lw_detr import *
|
| 235 |
+
from .lxmert import *
|
| 236 |
+
from .m2m_100 import *
|
| 237 |
+
from .mamba import *
|
| 238 |
+
from .mamba2 import *
|
| 239 |
+
from .marian import *
|
| 240 |
+
from .markuplm import *
|
| 241 |
+
from .mask2former import *
|
| 242 |
+
from .maskformer import *
|
| 243 |
+
from .mbart import *
|
| 244 |
+
from .mbart50 import *
|
| 245 |
+
from .megatron_bert import *
|
| 246 |
+
from .megatron_gpt2 import *
|
| 247 |
+
from .metaclip_2 import *
|
| 248 |
+
from .mgp_str import *
|
| 249 |
+
from .mimi import *
|
| 250 |
+
from .minimax import *
|
| 251 |
+
from .minimax_m2 import *
|
| 252 |
+
from .ministral import *
|
| 253 |
+
from .ministral3 import *
|
| 254 |
+
from .mistral import *
|
| 255 |
+
from .mistral3 import *
|
| 256 |
+
from .mistral4 import *
|
| 257 |
+
from .mixtral import *
|
| 258 |
+
from .mlcd import *
|
| 259 |
+
from .mllama import *
|
| 260 |
+
from .mluke import *
|
| 261 |
+
from .mm_grounding_dino import *
|
| 262 |
+
from .mobilebert import *
|
| 263 |
+
from .mobilenet_v1 import *
|
| 264 |
+
from .mobilenet_v2 import *
|
| 265 |
+
from .mobilevit import *
|
| 266 |
+
from .mobilevitv2 import *
|
| 267 |
+
from .modernbert import *
|
| 268 |
+
from .modernbert_decoder import *
|
| 269 |
+
from .modernvbert import *
|
| 270 |
+
from .moonshine import *
|
| 271 |
+
from .moonshine_streaming import *
|
| 272 |
+
from .moshi import *
|
| 273 |
+
from .mpnet import *
|
| 274 |
+
from .mpt import *
|
| 275 |
+
from .mra import *
|
| 276 |
+
from .mt5 import *
|
| 277 |
+
from .musicflamingo import *
|
| 278 |
+
from .musicgen import *
|
| 279 |
+
from .musicgen_melody import *
|
| 280 |
+
from .mvp import *
|
| 281 |
+
from .myt5 import *
|
| 282 |
+
from .nanochat import *
|
| 283 |
+
from .nemotron import *
|
| 284 |
+
from .nemotron_h import *
|
| 285 |
+
from .nllb import *
|
| 286 |
+
from .nllb_moe import *
|
| 287 |
+
from .nomic_bert import *
|
| 288 |
+
from .nougat import *
|
| 289 |
+
from .nystromformer import *
|
| 290 |
+
from .olmo import *
|
| 291 |
+
from .olmo2 import *
|
| 292 |
+
from .olmo3 import *
|
| 293 |
+
from .olmo_hybrid import *
|
| 294 |
+
from .olmoe import *
|
| 295 |
+
from .omdet_turbo import *
|
| 296 |
+
from .oneformer import *
|
| 297 |
+
from .openai import *
|
| 298 |
+
from .opt import *
|
| 299 |
+
from .ovis2 import *
|
| 300 |
+
from .owlv2 import *
|
| 301 |
+
from .owlvit import *
|
| 302 |
+
from .paddleocr_vl import *
|
| 303 |
+
from .paligemma import *
|
| 304 |
+
from .parakeet import *
|
| 305 |
+
from .patchtsmixer import *
|
| 306 |
+
from .patchtst import *
|
| 307 |
+
from .pe_audio import *
|
| 308 |
+
from .pe_audio_video import *
|
| 309 |
+
from .pe_video import *
|
| 310 |
+
from .pegasus import *
|
| 311 |
+
from .pegasus_x import *
|
| 312 |
+
from .perceiver import *
|
| 313 |
+
from .perception_lm import *
|
| 314 |
+
from .persimmon import *
|
| 315 |
+
from .phi import *
|
| 316 |
+
from .phi3 import *
|
| 317 |
+
from .phi4_multimodal import *
|
| 318 |
+
from .phimoe import *
|
| 319 |
+
from .phobert import *
|
| 320 |
+
from .pi0 import *
|
| 321 |
+
from .pi0_fast import *
|
| 322 |
+
from .pix2struct import *
|
| 323 |
+
from .pixio import *
|
| 324 |
+
from .pixtral import *
|
| 325 |
+
from .plbart import *
|
| 326 |
+
from .poolformer import *
|
| 327 |
+
from .pop2piano import *
|
| 328 |
+
from .pp_chart2table import *
|
| 329 |
+
from .pp_doclayout_v2 import *
|
| 330 |
+
from .pp_doclayout_v3 import *
|
| 331 |
+
from .pp_lcnet import *
|
| 332 |
+
from .pp_lcnet_v3 import *
|
| 333 |
+
from .pp_ocrv5_mobile_det import *
|
| 334 |
+
from .pp_ocrv5_server_det import *
|
| 335 |
+
from .prompt_depth_anything import *
|
| 336 |
+
from .prophetnet import *
|
| 337 |
+
from .pvt import *
|
| 338 |
+
from .pvt_v2 import *
|
| 339 |
+
from .qwen2 import *
|
| 340 |
+
from .qwen2_5_omni import *
|
| 341 |
+
from .qwen2_5_vl import *
|
| 342 |
+
from .qwen2_audio import *
|
| 343 |
+
from .qwen2_moe import *
|
| 344 |
+
from .qwen2_vl import *
|
| 345 |
+
from .qwen3 import *
|
| 346 |
+
from .qwen3_5 import *
|
| 347 |
+
from .qwen3_5_moe import *
|
| 348 |
+
from .qwen3_moe import *
|
| 349 |
+
from .qwen3_next import *
|
| 350 |
+
from .qwen3_omni_moe import *
|
| 351 |
+
from .qwen3_vl import *
|
| 352 |
+
from .qwen3_vl_moe import *
|
| 353 |
+
from .rag import *
|
| 354 |
+
from .recurrent_gemma import *
|
| 355 |
+
from .reformer import *
|
| 356 |
+
from .regnet import *
|
| 357 |
+
from .rembert import *
|
| 358 |
+
from .resnet import *
|
| 359 |
+
from .roberta import *
|
| 360 |
+
from .roberta_prelayernorm import *
|
| 361 |
+
from .roc_bert import *
|
| 362 |
+
from .roformer import *
|
| 363 |
+
from .rt_detr import *
|
| 364 |
+
from .rt_detr_v2 import *
|
| 365 |
+
from .rwkv import *
|
| 366 |
+
from .sam import *
|
| 367 |
+
from .sam2 import *
|
| 368 |
+
from .sam2_video import *
|
| 369 |
+
from .sam3 import *
|
| 370 |
+
from .sam3_tracker import *
|
| 371 |
+
from .sam3_tracker_video import *
|
| 372 |
+
from .sam3_video import *
|
| 373 |
+
from .sam_hq import *
|
| 374 |
+
from .seamless_m4t import *
|
| 375 |
+
from .seamless_m4t_v2 import *
|
| 376 |
+
from .seed_oss import *
|
| 377 |
+
from .segformer import *
|
| 378 |
+
from .seggpt import *
|
| 379 |
+
from .sew import *
|
| 380 |
+
from .sew_d import *
|
| 381 |
+
from .shieldgemma2 import *
|
| 382 |
+
from .siglip import *
|
| 383 |
+
from .siglip2 import *
|
| 384 |
+
from .slanext import *
|
| 385 |
+
from .smollm3 import *
|
| 386 |
+
from .smolvlm import *
|
| 387 |
+
from .solar_open import *
|
| 388 |
+
from .speech_encoder_decoder import *
|
| 389 |
+
from .speech_to_text import *
|
| 390 |
+
from .speecht5 import *
|
| 391 |
+
from .splinter import *
|
| 392 |
+
from .squeezebert import *
|
| 393 |
+
from .stablelm import *
|
| 394 |
+
from .starcoder2 import *
|
| 395 |
+
from .superglue import *
|
| 396 |
+
from .superpoint import *
|
| 397 |
+
from .swiftformer import *
|
| 398 |
+
from .swin import *
|
| 399 |
+
from .swin2sr import *
|
| 400 |
+
from .swinv2 import *
|
| 401 |
+
from .switch_transformers import *
|
| 402 |
+
from .t5 import *
|
| 403 |
+
from .t5gemma import *
|
| 404 |
+
from .t5gemma2 import *
|
| 405 |
+
from .table_transformer import *
|
| 406 |
+
from .tapas import *
|
| 407 |
+
from .textnet import *
|
| 408 |
+
from .time_series_transformer import *
|
| 409 |
+
from .timesfm import *
|
| 410 |
+
from .timesfm2_5 import *
|
| 411 |
+
from .timesformer import *
|
| 412 |
+
from .timm_backbone import *
|
| 413 |
+
from .timm_wrapper import *
|
| 414 |
+
from .trocr import *
|
| 415 |
+
from .tvp import *
|
| 416 |
+
from .udop import *
|
| 417 |
+
from .umt5 import *
|
| 418 |
+
from .unispeech import *
|
| 419 |
+
from .unispeech_sat import *
|
| 420 |
+
from .univnet import *
|
| 421 |
+
from .upernet import *
|
| 422 |
+
from .uvdoc import *
|
| 423 |
+
from .vaultgemma import *
|
| 424 |
+
from .vibevoice_asr import *
|
| 425 |
+
from .video_llama_3 import *
|
| 426 |
+
from .video_llava import *
|
| 427 |
+
from .videomae import *
|
| 428 |
+
from .videomt import *
|
| 429 |
+
from .vilt import *
|
| 430 |
+
from .vipllava import *
|
| 431 |
+
from .vision_encoder_decoder import *
|
| 432 |
+
from .vision_text_dual_encoder import *
|
| 433 |
+
from .visual_bert import *
|
| 434 |
+
from .vit import *
|
| 435 |
+
from .vit_mae import *
|
| 436 |
+
from .vit_msn import *
|
| 437 |
+
from .vitdet import *
|
| 438 |
+
from .vitmatte import *
|
| 439 |
+
from .vitpose import *
|
| 440 |
+
from .vitpose_backbone import *
|
| 441 |
+
from .vits import *
|
| 442 |
+
from .vivit import *
|
| 443 |
+
from .vjepa2 import *
|
| 444 |
+
from .voxtral import *
|
| 445 |
+
from .voxtral_realtime import *
|
| 446 |
+
from .wav2vec2 import *
|
| 447 |
+
from .wav2vec2_bert import *
|
| 448 |
+
from .wav2vec2_conformer import *
|
| 449 |
+
from .wav2vec2_phoneme import *
|
| 450 |
+
from .wav2vec2_with_lm import *
|
| 451 |
+
from .wavlm import *
|
| 452 |
+
from .whisper import *
|
| 453 |
+
from .x_clip import *
|
| 454 |
+
from .xcodec import *
|
| 455 |
+
from .xglm import *
|
| 456 |
+
from .xlm import *
|
| 457 |
+
from .xlm_roberta import *
|
| 458 |
+
from .xlm_roberta_xl import *
|
| 459 |
+
from .xlnet import *
|
| 460 |
+
from .xlstm import *
|
| 461 |
+
from .xmod import *
|
| 462 |
+
from .yolos import *
|
| 463 |
+
from .yoso import *
|
| 464 |
+
from .youtu import *
|
| 465 |
+
from .zamba import *
|
| 466 |
+
from .zamba2 import *
|
| 467 |
+
from .zoedepth import *
|
| 468 |
+
else:
|
| 469 |
+
import sys
|
| 470 |
+
|
| 471 |
+
_file = globals()["__file__"]
|
| 472 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/beit/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_beit import *
|
| 22 |
+
from .image_processing_beit import *
|
| 23 |
+
from .image_processing_pil_beit import *
|
| 24 |
+
from .modeling_beit import *
|
| 25 |
+
else:
|
| 26 |
+
import sys
|
| 27 |
+
|
| 28 |
+
_file = globals()["__file__"]
|
| 29 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/beit/configuration_beit.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Microsoft Research and The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""BEiT model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...backbone_utils import BackboneConfigMixin
|
| 19 |
+
from ...configuration_utils import PreTrainedConfig
|
| 20 |
+
from ...utils import auto_docstring
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
@auto_docstring(checkpoint="microsoft/beit-base-patch16-224-pt22k")
|
| 24 |
+
@strict
|
| 25 |
+
class BeitConfig(BackboneConfigMixin, PreTrainedConfig):
|
| 26 |
+
r"""
|
| 27 |
+
use_mask_token (`bool`, *optional*, defaults to `False`):
|
| 28 |
+
Whether to use a mask token for masked image modeling.
|
| 29 |
+
use_relative_position_bias (`bool`, *optional*, defaults to `False`):
|
| 30 |
+
Whether to use T5-style relative position embeddings in the self-attention layers.
|
| 31 |
+
use_shared_relative_position_bias (`bool`, *optional*, defaults to `False`):
|
| 32 |
+
Whether to use the same relative position embeddings across all self-attention layers of the Transformer.
|
| 33 |
+
use_mean_pooling (`bool`, *optional*, defaults to `True`):
|
| 34 |
+
Whether to mean pool the final hidden states of the patches instead of using the final hidden state of the
|
| 35 |
+
CLS token, before applying the classification head.
|
| 36 |
+
pool_scales (`tuple[int]`, *optional*, defaults to `[1, 2, 3, 6]`):
|
| 37 |
+
Pooling scales used in Pooling Pyramid Module applied on the last feature map.
|
| 38 |
+
use_auxiliary_head (`bool`, *optional*, defaults to `True`):
|
| 39 |
+
Whether to use an auxiliary head during training.
|
| 40 |
+
auxiliary_loss_weight (`float`, *optional*, defaults to 0.4):
|
| 41 |
+
Weight of the cross-entropy loss of the auxiliary head.
|
| 42 |
+
auxiliary_channels (`int`, *optional*, defaults to 256):
|
| 43 |
+
Number of channels to use in the auxiliary head.
|
| 44 |
+
auxiliary_num_convs (`int`, *optional*, defaults to 1):
|
| 45 |
+
Number of convolutional layers to use in the auxiliary head.
|
| 46 |
+
auxiliary_concat_input (`bool`, *optional*, defaults to `False`):
|
| 47 |
+
Whether to concatenate the output of the auxiliary head with the input before the classification layer.
|
| 48 |
+
add_fpn (`bool`, *optional*, defaults to `False`):
|
| 49 |
+
Whether to add a FPN as part of the backbone. Only relevant for [`BeitBackbone`].
|
| 50 |
+
reshape_hidden_states (`bool`, *optional*, defaults to `True`):
|
| 51 |
+
Whether to reshape the feature maps to 4D tensors of shape `(batch_size, hidden_size, height, width)` in
|
| 52 |
+
case the model is used as backbone. If `False`, the feature maps will be 3D tensors of shape `(batch_size,
|
| 53 |
+
seq_len, hidden_size)`. Only relevant for [`BeitBackbone`].
|
| 54 |
+
|
| 55 |
+
Example:
|
| 56 |
+
|
| 57 |
+
```python
|
| 58 |
+
>>> from transformers import BeitConfig, BeitModel
|
| 59 |
+
|
| 60 |
+
>>> # Initializing a BEiT beit-base-patch16-224-pt22k style configuration
|
| 61 |
+
>>> configuration = BeitConfig()
|
| 62 |
+
|
| 63 |
+
>>> # Initializing a model (with random weights) from the beit-base-patch16-224-pt22k style configuration
|
| 64 |
+
>>> model = BeitModel(configuration)
|
| 65 |
+
|
| 66 |
+
>>> # Accessing the model configuration
|
| 67 |
+
>>> configuration = model.config
|
| 68 |
+
```"""
|
| 69 |
+
|
| 70 |
+
model_type = "beit"
|
| 71 |
+
|
| 72 |
+
vocab_size: int = 8192
|
| 73 |
+
hidden_size: int = 768
|
| 74 |
+
num_hidden_layers: int = 12
|
| 75 |
+
num_attention_heads: int = 12
|
| 76 |
+
intermediate_size: int = 3072
|
| 77 |
+
hidden_act: str = "gelu"
|
| 78 |
+
hidden_dropout_prob: float | int = 0.0
|
| 79 |
+
attention_probs_dropout_prob: float | int = 0.0
|
| 80 |
+
initializer_range: float = 0.02
|
| 81 |
+
layer_norm_eps: float = 1e-12
|
| 82 |
+
image_size: int | list[int] | tuple[int, int] = 224
|
| 83 |
+
patch_size: int | list[int] | tuple[int, int] = 16
|
| 84 |
+
num_channels: int = 3
|
| 85 |
+
use_mask_token: bool = False
|
| 86 |
+
use_absolute_position_embeddings: bool = False
|
| 87 |
+
use_relative_position_bias: bool = False
|
| 88 |
+
use_shared_relative_position_bias: bool = False
|
| 89 |
+
layer_scale_init_value: float = 0.1
|
| 90 |
+
drop_path_rate: float | int = 0.1
|
| 91 |
+
use_mean_pooling: bool = True
|
| 92 |
+
pool_scales: list[int] | tuple[int, ...] = (1, 2, 3, 6)
|
| 93 |
+
use_auxiliary_head: bool = True
|
| 94 |
+
auxiliary_loss_weight: float = 0.4
|
| 95 |
+
auxiliary_channels: int = 256
|
| 96 |
+
auxiliary_num_convs: int = 1
|
| 97 |
+
auxiliary_concat_input: bool = False
|
| 98 |
+
semantic_loss_ignore_index: int = 255
|
| 99 |
+
_out_features: list[str] | None = None
|
| 100 |
+
_out_indices: list[int] | None = None
|
| 101 |
+
add_fpn: bool = False
|
| 102 |
+
reshape_hidden_states: bool = True
|
| 103 |
+
|
| 104 |
+
def __post_init__(self, **kwargs):
|
| 105 |
+
if "segmentation_indices" in kwargs and kwargs.get("out_indices") is None:
|
| 106 |
+
kwargs["out_indices"] = kwargs.pop("segmentation_indices")
|
| 107 |
+
|
| 108 |
+
# backbone attributes
|
| 109 |
+
self.stage_names = ["stem"] + [f"stage{idx}" for idx in range(1, self.num_hidden_layers + 1)]
|
| 110 |
+
self.set_output_features_output_indices(
|
| 111 |
+
out_indices=kwargs.pop("out_indices", None), out_features=kwargs.pop("out_features", None)
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
super().__post_init__(**kwargs)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
__all__ = ["BeitConfig"]
|
third_party/transformers/src/transformers/models/beit/convert_beit_unilm_to_pytorch.py
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert BEiT checkpoints from the unilm repository."""
|
| 15 |
+
|
| 16 |
+
import argparse
|
| 17 |
+
import json
|
| 18 |
+
from io import BytesIO
|
| 19 |
+
from pathlib import Path
|
| 20 |
+
|
| 21 |
+
import httpx
|
| 22 |
+
import torch
|
| 23 |
+
from datasets import load_dataset
|
| 24 |
+
from huggingface_hub import hf_hub_download
|
| 25 |
+
from PIL import Image
|
| 26 |
+
|
| 27 |
+
from transformers import (
|
| 28 |
+
BeitConfig,
|
| 29 |
+
BeitForImageClassification,
|
| 30 |
+
BeitForMaskedImageModeling,
|
| 31 |
+
BeitForSemanticSegmentation,
|
| 32 |
+
BeitImageProcessor,
|
| 33 |
+
)
|
| 34 |
+
from transformers.image_utils import PILImageResampling
|
| 35 |
+
from transformers.utils import logging
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
logging.set_verbosity_info()
|
| 39 |
+
logger = logging.get_logger(__name__)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
# here we list all keys to be renamed (original name on the left, our name on the right)
|
| 43 |
+
def create_rename_keys(config, has_lm_head=False, is_semantic=False):
|
| 44 |
+
prefix = "backbone." if is_semantic else ""
|
| 45 |
+
|
| 46 |
+
rename_keys = []
|
| 47 |
+
for i in range(config.num_hidden_layers):
|
| 48 |
+
# encoder layers: output projection, 2 feedforward neural networks and 2 layernorms
|
| 49 |
+
rename_keys.append((f"{prefix}blocks.{i}.norm1.weight", f"beit.encoder.layer.{i}.layernorm_before.weight"))
|
| 50 |
+
rename_keys.append((f"{prefix}blocks.{i}.norm1.bias", f"beit.encoder.layer.{i}.layernorm_before.bias"))
|
| 51 |
+
rename_keys.append(
|
| 52 |
+
(f"{prefix}blocks.{i}.attn.proj.weight", f"beit.encoder.layer.{i}.attention.output.dense.weight")
|
| 53 |
+
)
|
| 54 |
+
rename_keys.append(
|
| 55 |
+
(f"{prefix}blocks.{i}.attn.proj.bias", f"beit.encoder.layer.{i}.attention.output.dense.bias")
|
| 56 |
+
)
|
| 57 |
+
rename_keys.append((f"{prefix}blocks.{i}.norm2.weight", f"beit.encoder.layer.{i}.layernorm_after.weight"))
|
| 58 |
+
rename_keys.append((f"{prefix}blocks.{i}.norm2.bias", f"beit.encoder.layer.{i}.layernorm_after.bias"))
|
| 59 |
+
rename_keys.append((f"{prefix}blocks.{i}.mlp.fc1.weight", f"beit.encoder.layer.{i}.intermediate.dense.weight"))
|
| 60 |
+
rename_keys.append((f"{prefix}blocks.{i}.mlp.fc1.bias", f"beit.encoder.layer.{i}.intermediate.dense.bias"))
|
| 61 |
+
rename_keys.append((f"{prefix}blocks.{i}.mlp.fc2.weight", f"beit.encoder.layer.{i}.output.dense.weight"))
|
| 62 |
+
rename_keys.append((f"{prefix}blocks.{i}.mlp.fc2.bias", f"beit.encoder.layer.{i}.output.dense.bias"))
|
| 63 |
+
|
| 64 |
+
# projection layer + position embeddings
|
| 65 |
+
rename_keys.extend(
|
| 66 |
+
[
|
| 67 |
+
(f"{prefix}cls_token", "beit.embeddings.cls_token"),
|
| 68 |
+
(f"{prefix}patch_embed.proj.weight", "beit.embeddings.patch_embeddings.projection.weight"),
|
| 69 |
+
(f"{prefix}patch_embed.proj.bias", "beit.embeddings.patch_embeddings.projection.bias"),
|
| 70 |
+
]
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
if has_lm_head:
|
| 74 |
+
# mask token + shared relative position bias + layernorm
|
| 75 |
+
rename_keys.extend(
|
| 76 |
+
[
|
| 77 |
+
("mask_token", "beit.embeddings.mask_token"),
|
| 78 |
+
(
|
| 79 |
+
"rel_pos_bias.relative_position_bias_table",
|
| 80 |
+
"beit.encoder.relative_position_bias.relative_position_bias_table",
|
| 81 |
+
),
|
| 82 |
+
(
|
| 83 |
+
"rel_pos_bias.relative_position_index",
|
| 84 |
+
"beit.encoder.relative_position_bias.relative_position_index",
|
| 85 |
+
),
|
| 86 |
+
("norm.weight", "layernorm.weight"),
|
| 87 |
+
("norm.bias", "layernorm.bias"),
|
| 88 |
+
]
|
| 89 |
+
)
|
| 90 |
+
elif is_semantic:
|
| 91 |
+
# semantic segmentation classification heads
|
| 92 |
+
rename_keys.extend(
|
| 93 |
+
[
|
| 94 |
+
("decode_head.conv_seg.weight", "decode_head.classifier.weight"),
|
| 95 |
+
("decode_head.conv_seg.bias", "decode_head.classifier.bias"),
|
| 96 |
+
("auxiliary_head.conv_seg.weight", "auxiliary_head.classifier.weight"),
|
| 97 |
+
("auxiliary_head.conv_seg.bias", "auxiliary_head.classifier.bias"),
|
| 98 |
+
]
|
| 99 |
+
)
|
| 100 |
+
else:
|
| 101 |
+
# layernorm + classification head
|
| 102 |
+
rename_keys.extend(
|
| 103 |
+
[
|
| 104 |
+
("fc_norm.weight", "beit.pooler.layernorm.weight"),
|
| 105 |
+
("fc_norm.bias", "beit.pooler.layernorm.bias"),
|
| 106 |
+
("head.weight", "classifier.weight"),
|
| 107 |
+
("head.bias", "classifier.bias"),
|
| 108 |
+
]
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
return rename_keys
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 115 |
+
def read_in_q_k_v(state_dict, config, has_lm_head=False, is_semantic=False):
|
| 116 |
+
for i in range(config.num_hidden_layers):
|
| 117 |
+
prefix = "backbone." if is_semantic else ""
|
| 118 |
+
# queries, keys and values
|
| 119 |
+
in_proj_weight = state_dict.pop(f"{prefix}blocks.{i}.attn.qkv.weight")
|
| 120 |
+
q_bias = state_dict.pop(f"{prefix}blocks.{i}.attn.q_bias")
|
| 121 |
+
v_bias = state_dict.pop(f"{prefix}blocks.{i}.attn.v_bias")
|
| 122 |
+
|
| 123 |
+
state_dict[f"beit.encoder.layer.{i}.attention.attention.query.weight"] = in_proj_weight[
|
| 124 |
+
: config.hidden_size, :
|
| 125 |
+
]
|
| 126 |
+
state_dict[f"beit.encoder.layer.{i}.attention.attention.query.bias"] = q_bias
|
| 127 |
+
state_dict[f"beit.encoder.layer.{i}.attention.attention.key.weight"] = in_proj_weight[
|
| 128 |
+
config.hidden_size : config.hidden_size * 2, :
|
| 129 |
+
]
|
| 130 |
+
state_dict[f"beit.encoder.layer.{i}.attention.attention.value.weight"] = in_proj_weight[
|
| 131 |
+
-config.hidden_size :, :
|
| 132 |
+
]
|
| 133 |
+
state_dict[f"beit.encoder.layer.{i}.attention.attention.value.bias"] = v_bias
|
| 134 |
+
|
| 135 |
+
# gamma_1 and gamma_2
|
| 136 |
+
# we call them lambda because otherwise they are renamed when using .from_pretrained
|
| 137 |
+
gamma_1 = state_dict.pop(f"{prefix}blocks.{i}.gamma_1")
|
| 138 |
+
gamma_2 = state_dict.pop(f"{prefix}blocks.{i}.gamma_2")
|
| 139 |
+
|
| 140 |
+
state_dict[f"beit.encoder.layer.{i}.lambda_1"] = gamma_1
|
| 141 |
+
state_dict[f"beit.encoder.layer.{i}.lambda_2"] = gamma_2
|
| 142 |
+
|
| 143 |
+
# relative_position bias table + index
|
| 144 |
+
if not has_lm_head:
|
| 145 |
+
# each layer has its own relative position bias
|
| 146 |
+
table = state_dict.pop(f"{prefix}blocks.{i}.attn.relative_position_bias_table")
|
| 147 |
+
index = state_dict.pop(f"{prefix}blocks.{i}.attn.relative_position_index")
|
| 148 |
+
|
| 149 |
+
state_dict[
|
| 150 |
+
f"beit.encoder.layer.{i}.attention.attention.relative_position_bias.relative_position_bias_table"
|
| 151 |
+
] = table
|
| 152 |
+
state_dict[
|
| 153 |
+
f"beit.encoder.layer.{i}.attention.attention.relative_position_bias.relative_position_index"
|
| 154 |
+
] = index
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def rename_key(dct, old, new):
|
| 158 |
+
val = dct.pop(old)
|
| 159 |
+
dct[new] = val
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
# We will verify our results on an image of cute cats
|
| 163 |
+
def prepare_img():
|
| 164 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 165 |
+
with httpx.stream("GET", url) as response:
|
| 166 |
+
image = Image.open(BytesIO(response.read()))
|
| 167 |
+
return image
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
@torch.no_grad()
|
| 171 |
+
def convert_beit_checkpoint(checkpoint_url, pytorch_dump_folder_path):
|
| 172 |
+
"""
|
| 173 |
+
Copy/paste/tweak model's weights to our BEiT structure.
|
| 174 |
+
"""
|
| 175 |
+
|
| 176 |
+
# define default BEiT configuration
|
| 177 |
+
config = BeitConfig()
|
| 178 |
+
has_lm_head = False
|
| 179 |
+
is_semantic = False
|
| 180 |
+
repo_id = "huggingface/label-files"
|
| 181 |
+
# set config parameters based on URL
|
| 182 |
+
if checkpoint_url[-9:-4] == "pt22k":
|
| 183 |
+
# masked image modeling
|
| 184 |
+
config.use_shared_relative_position_bias = True
|
| 185 |
+
config.use_mask_token = True
|
| 186 |
+
has_lm_head = True
|
| 187 |
+
elif checkpoint_url[-9:-4] == "ft22k":
|
| 188 |
+
# intermediate fine-tuning on ImageNet-22k
|
| 189 |
+
config.use_relative_position_bias = True
|
| 190 |
+
config.num_labels = 21841
|
| 191 |
+
filename = "imagenet-22k-id2label.json"
|
| 192 |
+
id2label = json.load(open(hf_hub_download(repo_id, filename, repo_type="dataset"), "r"))
|
| 193 |
+
id2label = {int(k): v for k, v in id2label.items()}
|
| 194 |
+
# this dataset contains 21843 labels but the model only has 21841
|
| 195 |
+
# we delete the classes as mentioned in https://github.com/google-research/big_transfer/issues/18
|
| 196 |
+
del id2label[9205]
|
| 197 |
+
del id2label[15027]
|
| 198 |
+
config.id2label = id2label
|
| 199 |
+
config.label2id = {v: k for k, v in id2label.items()}
|
| 200 |
+
elif checkpoint_url[-8:-4] == "to1k":
|
| 201 |
+
# fine-tuning on ImageNet-1k
|
| 202 |
+
config.use_relative_position_bias = True
|
| 203 |
+
config.num_labels = 1000
|
| 204 |
+
filename = "imagenet-1k-id2label.json"
|
| 205 |
+
id2label = json.load(open(hf_hub_download(repo_id, filename, repo_type="dataset"), "r"))
|
| 206 |
+
id2label = {int(k): v for k, v in id2label.items()}
|
| 207 |
+
config.id2label = id2label
|
| 208 |
+
config.label2id = {v: k for k, v in id2label.items()}
|
| 209 |
+
if "384" in checkpoint_url:
|
| 210 |
+
config.image_size = 384
|
| 211 |
+
if "512" in checkpoint_url:
|
| 212 |
+
config.image_size = 512
|
| 213 |
+
elif "ade20k" in checkpoint_url:
|
| 214 |
+
# fine-tuning
|
| 215 |
+
config.use_relative_position_bias = True
|
| 216 |
+
config.num_labels = 150
|
| 217 |
+
filename = "ade20k-id2label.json"
|
| 218 |
+
id2label = json.load(open(hf_hub_download(repo_id, filename, repo_type="dataset"), "r"))
|
| 219 |
+
id2label = {int(k): v for k, v in id2label.items()}
|
| 220 |
+
config.id2label = id2label
|
| 221 |
+
config.label2id = {v: k for k, v in id2label.items()}
|
| 222 |
+
config.image_size = 640
|
| 223 |
+
is_semantic = True
|
| 224 |
+
else:
|
| 225 |
+
raise ValueError("Checkpoint not supported, URL should either end with 'pt22k', 'ft22k', 'to1k' or 'ade20k'")
|
| 226 |
+
|
| 227 |
+
# size of the architecture
|
| 228 |
+
if "base" in checkpoint_url:
|
| 229 |
+
if "ade20k" in checkpoint_url:
|
| 230 |
+
config.out_indices = [3, 5, 7, 11]
|
| 231 |
+
elif "large" in checkpoint_url:
|
| 232 |
+
config.hidden_size = 1024
|
| 233 |
+
config.intermediate_size = 4096
|
| 234 |
+
config.num_hidden_layers = 24
|
| 235 |
+
config.num_attention_heads = 16
|
| 236 |
+
if "ade20k" in checkpoint_url:
|
| 237 |
+
config.image_size = 640
|
| 238 |
+
config.out_indices = [7, 11, 15, 23]
|
| 239 |
+
else:
|
| 240 |
+
raise ValueError("Should either find 'base' or 'large' in checkpoint URL")
|
| 241 |
+
|
| 242 |
+
# load state_dict of original model, remove and rename some keys
|
| 243 |
+
state_dict = torch.hub.load_state_dict_from_url(checkpoint_url, map_location="cpu", check_hash=True)
|
| 244 |
+
state_dict = state_dict["model"] if "ade20k" not in checkpoint_url else state_dict["state_dict"]
|
| 245 |
+
|
| 246 |
+
rename_keys = create_rename_keys(config, has_lm_head=has_lm_head, is_semantic=is_semantic)
|
| 247 |
+
for src, dest in rename_keys:
|
| 248 |
+
rename_key(state_dict, src, dest)
|
| 249 |
+
read_in_q_k_v(state_dict, config, has_lm_head=has_lm_head, is_semantic=is_semantic)
|
| 250 |
+
if is_semantic:
|
| 251 |
+
# add prefix to decoder keys
|
| 252 |
+
for key, val in state_dict.copy().items():
|
| 253 |
+
val = state_dict.pop(key)
|
| 254 |
+
if key.startswith("backbone.fpn"):
|
| 255 |
+
key = key.replace("backbone.fpn", "fpn")
|
| 256 |
+
state_dict[key] = val
|
| 257 |
+
|
| 258 |
+
# load HuggingFace model
|
| 259 |
+
if checkpoint_url[-9:-4] == "pt22k":
|
| 260 |
+
model = BeitForMaskedImageModeling(config)
|
| 261 |
+
elif "ade20k" in checkpoint_url:
|
| 262 |
+
model = BeitForSemanticSegmentation(config)
|
| 263 |
+
else:
|
| 264 |
+
model = BeitForImageClassification(config)
|
| 265 |
+
model.eval()
|
| 266 |
+
model.load_state_dict(state_dict)
|
| 267 |
+
|
| 268 |
+
# Check outputs on an image
|
| 269 |
+
if is_semantic:
|
| 270 |
+
image_processor = BeitImageProcessor(size=config.image_size, do_center_crop=False)
|
| 271 |
+
ds = load_dataset("hf-internal-testing/fixtures_ade20k", split="test")
|
| 272 |
+
image = Image.open(ds[0]["file"])
|
| 273 |
+
else:
|
| 274 |
+
image_processor = BeitImageProcessor(
|
| 275 |
+
size=config.image_size, resample=PILImageResampling.BILINEAR, do_center_crop=False
|
| 276 |
+
)
|
| 277 |
+
image = prepare_img()
|
| 278 |
+
|
| 279 |
+
encoding = image_processor(images=image, return_tensors="pt")
|
| 280 |
+
pixel_values = encoding["pixel_values"]
|
| 281 |
+
|
| 282 |
+
outputs = model(pixel_values)
|
| 283 |
+
logits = outputs.logits
|
| 284 |
+
|
| 285 |
+
# verify logits
|
| 286 |
+
expected_shape = torch.Size([1, 1000])
|
| 287 |
+
if checkpoint_url[:-4].endswith("beit_base_patch16_224_pt22k"):
|
| 288 |
+
expected_shape = torch.Size([1, 196, 8192])
|
| 289 |
+
elif checkpoint_url[:-4].endswith("beit_large_patch16_224_pt22k"):
|
| 290 |
+
expected_shape = torch.Size([1, 196, 8192])
|
| 291 |
+
elif checkpoint_url[:-4].endswith("beit_base_patch16_224_pt22k_ft22k"):
|
| 292 |
+
expected_shape = torch.Size([1, 21841])
|
| 293 |
+
expected_logits = torch.tensor([2.2288, 2.4671, 0.7395])
|
| 294 |
+
expected_class_idx = 2397
|
| 295 |
+
elif checkpoint_url[:-4].endswith("beit_large_patch16_224_pt22k_ft22k"):
|
| 296 |
+
expected_shape = torch.Size([1, 21841])
|
| 297 |
+
expected_logits = torch.tensor([1.6881, -0.2787, 0.5901])
|
| 298 |
+
expected_class_idx = 2396
|
| 299 |
+
elif checkpoint_url[:-4].endswith("beit_base_patch16_224_pt22k_ft1k"):
|
| 300 |
+
expected_logits = torch.tensor([0.1241, 0.0798, -0.6569])
|
| 301 |
+
expected_class_idx = 285
|
| 302 |
+
elif checkpoint_url[:-4].endswith("beit_base_patch16_224_pt22k_ft22kto1k"):
|
| 303 |
+
expected_logits = torch.tensor([-1.2385, -1.0987, -1.0108])
|
| 304 |
+
expected_class_idx = 281
|
| 305 |
+
elif checkpoint_url[:-4].endswith("beit_base_patch16_384_pt22k_ft22kto1k"):
|
| 306 |
+
expected_logits = torch.tensor([-1.5303, -0.9484, -0.3147])
|
| 307 |
+
expected_class_idx = 761
|
| 308 |
+
elif checkpoint_url[:-4].endswith("beit_large_patch16_224_pt22k_ft1k"):
|
| 309 |
+
expected_logits = torch.tensor([0.4610, -0.0928, 0.2086])
|
| 310 |
+
expected_class_idx = 761
|
| 311 |
+
elif checkpoint_url[:-4].endswith("beit_large_patch16_224_pt22k_ft22kto1k"):
|
| 312 |
+
expected_logits = torch.tensor([-0.4804, 0.6257, -0.1837])
|
| 313 |
+
expected_class_idx = 761
|
| 314 |
+
elif checkpoint_url[:-4].endswith("beit_large_patch16_384_pt22k_ft22kto1k"):
|
| 315 |
+
expected_logits = torch.tensor([[-0.5122, 0.5117, -0.2113]])
|
| 316 |
+
expected_class_idx = 761
|
| 317 |
+
elif checkpoint_url[:-4].endswith("beit_large_patch16_512_pt22k_ft22kto1k"):
|
| 318 |
+
expected_logits = torch.tensor([-0.3062, 0.7261, 0.4852])
|
| 319 |
+
expected_class_idx = 761
|
| 320 |
+
elif checkpoint_url[:-4].endswith("beit_base_patch16_640_pt22k_ft22ktoade20k"):
|
| 321 |
+
expected_shape = (1, 150, 160, 160)
|
| 322 |
+
expected_logits = torch.tensor(
|
| 323 |
+
[
|
| 324 |
+
[[-4.9225, -2.3954, -3.0522], [-2.8822, -1.0046, -1.7561], [-2.9549, -1.3228, -2.1347]],
|
| 325 |
+
[[-5.8168, -3.4129, -4.0778], [-3.8651, -2.2214, -3.0277], [-3.8356, -2.4643, -3.3535]],
|
| 326 |
+
[[-0.0078, 3.9952, 4.0754], [2.9856, 4.6944, 5.0035], [3.2413, 4.7813, 4.9969]],
|
| 327 |
+
]
|
| 328 |
+
)
|
| 329 |
+
elif checkpoint_url[:-4].endswith("beit_large_patch16_640_pt22k_ft22ktoade20k"):
|
| 330 |
+
expected_shape = (1, 150, 160, 160)
|
| 331 |
+
expected_logits = torch.tensor(
|
| 332 |
+
[
|
| 333 |
+
[[-4.3305, -2.3049, -3.0161], [-2.9591, -1.5305, -2.2251], [-3.4198, -1.8004, -2.9062]],
|
| 334 |
+
[[-5.8922, -3.7435, -4.3978], [-4.2063, -2.7872, -3.4755], [-4.2791, -3.1874, -4.1681]],
|
| 335 |
+
[[0.9895, 4.3467, 4.7663], [4.2476, 5.6830, 6.1518], [4.5550, 6.2495, 6.5154]],
|
| 336 |
+
]
|
| 337 |
+
)
|
| 338 |
+
else:
|
| 339 |
+
raise ValueError("Can't verify logits as model is not supported")
|
| 340 |
+
|
| 341 |
+
if logits.shape != expected_shape:
|
| 342 |
+
raise ValueError(f"Shape of logits not as expected. {logits.shape=}, {expected_shape=}")
|
| 343 |
+
if not has_lm_head:
|
| 344 |
+
if is_semantic:
|
| 345 |
+
if not torch.allclose(logits[0, :3, :3, :3], expected_logits, atol=1e-3):
|
| 346 |
+
raise ValueError("First elements of logits not as expected")
|
| 347 |
+
else:
|
| 348 |
+
print("Predicted class idx:", logits.argmax(-1).item())
|
| 349 |
+
|
| 350 |
+
if not torch.allclose(logits[0, :3], expected_logits, atol=1e-3):
|
| 351 |
+
raise ValueError("First elements of logits not as expected")
|
| 352 |
+
if logits.argmax(-1).item() != expected_class_idx:
|
| 353 |
+
raise ValueError("Predicted class index not as expected")
|
| 354 |
+
|
| 355 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 356 |
+
print(f"Saving model to {pytorch_dump_folder_path}")
|
| 357 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 358 |
+
print(f"Saving image processor to {pytorch_dump_folder_path}")
|
| 359 |
+
image_processor.save_pretrained(pytorch_dump_folder_path)
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
if __name__ == "__main__":
|
| 363 |
+
parser = argparse.ArgumentParser()
|
| 364 |
+
|
| 365 |
+
parser.add_argument(
|
| 366 |
+
"--checkpoint_url",
|
| 367 |
+
default="https://conversationhub.blob.core.windows.net/beit-share-public/beit/beit_base_patch16_224_pt22k_ft22kto1k.pth",
|
| 368 |
+
type=str,
|
| 369 |
+
help="URL to the original PyTorch checkpoint (.pth file).",
|
| 370 |
+
)
|
| 371 |
+
parser.add_argument(
|
| 372 |
+
"--pytorch_dump_folder_path", default=None, type=str, help="Path to the folder to output PyTorch model."
|
| 373 |
+
)
|
| 374 |
+
args = parser.parse_args()
|
| 375 |
+
convert_beit_checkpoint(args.checkpoint_url, args.pytorch_dump_folder_path)
|
third_party/transformers/src/transformers/models/beit/image_processing_beit.py
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Image processor class for BEiT."""
|
| 15 |
+
|
| 16 |
+
from typing import Union
|
| 17 |
+
|
| 18 |
+
import torch
|
| 19 |
+
import torch.nn.functional as F
|
| 20 |
+
from torchvision.transforms.v2 import functional as tvF
|
| 21 |
+
|
| 22 |
+
from ...image_processing_backends import TorchvisionBackend
|
| 23 |
+
from ...image_processing_utils import BatchFeature
|
| 24 |
+
from ...image_transforms import group_images_by_shape, reorder_images
|
| 25 |
+
from ...image_utils import (
|
| 26 |
+
IMAGENET_STANDARD_MEAN,
|
| 27 |
+
IMAGENET_STANDARD_STD,
|
| 28 |
+
ChannelDimension,
|
| 29 |
+
ImageInput,
|
| 30 |
+
PILImageResampling,
|
| 31 |
+
SizeDict,
|
| 32 |
+
)
|
| 33 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 34 |
+
from ...utils import TensorType, auto_docstring, is_torch_available
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class BeitImageProcessorKwargs(ImagesKwargs, total=False):
|
| 38 |
+
r"""
|
| 39 |
+
do_reduce_labels (`bool`, *optional*, defaults to `self.do_reduce_labels`):
|
| 40 |
+
Whether or not to reduce all label values of segmentation maps by 1. Usually used for datasets where 0
|
| 41 |
+
is used for background, and background itself is not included in all classes of a dataset (e.g.
|
| 42 |
+
ADE20k). The background label will be replaced by 255.
|
| 43 |
+
"""
|
| 44 |
+
|
| 45 |
+
do_reduce_labels: bool
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
@auto_docstring
|
| 49 |
+
class BeitImageProcessor(TorchvisionBackend):
|
| 50 |
+
"""PIL backend for BEiT with reduce_label support."""
|
| 51 |
+
|
| 52 |
+
valid_kwargs = BeitImageProcessorKwargs
|
| 53 |
+
|
| 54 |
+
resample = PILImageResampling.BICUBIC
|
| 55 |
+
image_mean = IMAGENET_STANDARD_MEAN
|
| 56 |
+
image_std = IMAGENET_STANDARD_STD
|
| 57 |
+
size = {"height": 224, "width": 224}
|
| 58 |
+
default_to_square = True
|
| 59 |
+
crop_size = {"height": 224, "width": 224}
|
| 60 |
+
do_resize = True
|
| 61 |
+
do_center_crop = False
|
| 62 |
+
do_rescale = True
|
| 63 |
+
do_normalize = True
|
| 64 |
+
do_reduce_labels = False
|
| 65 |
+
|
| 66 |
+
def __init__(self, **kwargs: Unpack[BeitImageProcessorKwargs]):
|
| 67 |
+
super().__init__(**kwargs)
|
| 68 |
+
|
| 69 |
+
@auto_docstring
|
| 70 |
+
def preprocess(
|
| 71 |
+
self,
|
| 72 |
+
images: ImageInput,
|
| 73 |
+
segmentation_maps: ImageInput | None = None,
|
| 74 |
+
**kwargs: Unpack[BeitImageProcessorKwargs],
|
| 75 |
+
) -> BatchFeature:
|
| 76 |
+
r"""
|
| 77 |
+
segmentation_maps (`ImageInput`, *optional*):
|
| 78 |
+
The segmentation maps to preprocess.
|
| 79 |
+
"""
|
| 80 |
+
return super().preprocess(images, segmentation_maps, **kwargs)
|
| 81 |
+
|
| 82 |
+
def _preprocess_image_like_inputs(
|
| 83 |
+
self,
|
| 84 |
+
images: ImageInput,
|
| 85 |
+
segmentation_maps: ImageInput | None,
|
| 86 |
+
do_convert_rgb: bool,
|
| 87 |
+
input_data_format: ChannelDimension,
|
| 88 |
+
return_tensors: str | TensorType | None,
|
| 89 |
+
device: Union[str, "torch.device"] | None = None,
|
| 90 |
+
**kwargs,
|
| 91 |
+
) -> BatchFeature:
|
| 92 |
+
"""Handle extra inputs beyond images."""
|
| 93 |
+
images = self._prepare_image_like_inputs(
|
| 94 |
+
images=images, do_convert_rgb=do_convert_rgb, input_data_format=input_data_format, device=device
|
| 95 |
+
)
|
| 96 |
+
images_kwargs = kwargs.copy()
|
| 97 |
+
images_kwargs["do_reduce_labels"] = False
|
| 98 |
+
data = {}
|
| 99 |
+
data["pixel_values"] = self._preprocess(images, **images_kwargs)
|
| 100 |
+
|
| 101 |
+
# Prepare segmentation maps if provided
|
| 102 |
+
if segmentation_maps is not None:
|
| 103 |
+
processed_segmentation_maps = self._prepare_image_like_inputs(
|
| 104 |
+
images=segmentation_maps,
|
| 105 |
+
expected_ndims=2,
|
| 106 |
+
do_convert_rgb=False,
|
| 107 |
+
input_data_format=ChannelDimension.FIRST,
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
# Process segmentation maps with do_normalize=False and do_rescale=False
|
| 111 |
+
segmentation_maps_kwargs = kwargs.copy()
|
| 112 |
+
segmentation_maps_kwargs.update({"do_normalize": False, "do_rescale": False})
|
| 113 |
+
processed_segmentation_maps = self._preprocess(
|
| 114 |
+
images=processed_segmentation_maps, **segmentation_maps_kwargs
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
# Convert to int64 and squeeze channel dimension
|
| 118 |
+
processed_segmentation_maps = [
|
| 119 |
+
processed_segmentation_map.squeeze(0).to(torch.int64)
|
| 120 |
+
for processed_segmentation_map in processed_segmentation_maps
|
| 121 |
+
]
|
| 122 |
+
data["labels"] = processed_segmentation_maps
|
| 123 |
+
|
| 124 |
+
return BatchFeature(data=data, tensor_type=return_tensors)
|
| 125 |
+
|
| 126 |
+
def reduce_label(self, labels: list["torch.Tensor"]) -> list["torch.Tensor"]:
|
| 127 |
+
"""Reduce label values by 1, replacing 0 with 255."""
|
| 128 |
+
for idx in range(len(labels)):
|
| 129 |
+
label = labels[idx]
|
| 130 |
+
label = torch.where(label == 0, torch.tensor(255, dtype=label.dtype, device=label.device), label)
|
| 131 |
+
label = label - 1
|
| 132 |
+
label = torch.where(label == 254, torch.tensor(255, dtype=label.dtype, device=label.device), label)
|
| 133 |
+
labels[idx] = label
|
| 134 |
+
return labels
|
| 135 |
+
|
| 136 |
+
def _preprocess(
|
| 137 |
+
self,
|
| 138 |
+
images: list["torch.Tensor"],
|
| 139 |
+
do_resize: bool,
|
| 140 |
+
size: SizeDict,
|
| 141 |
+
resample: "PILImageResampling | tvF.InterpolationMode | int | None",
|
| 142 |
+
do_center_crop: bool,
|
| 143 |
+
crop_size: SizeDict,
|
| 144 |
+
do_rescale: bool,
|
| 145 |
+
rescale_factor: float,
|
| 146 |
+
do_normalize: bool,
|
| 147 |
+
image_mean: float | list[float] | None,
|
| 148 |
+
image_std: float | list[float] | None,
|
| 149 |
+
disable_grouping: bool | None,
|
| 150 |
+
do_reduce_labels: bool = False,
|
| 151 |
+
**kwargs,
|
| 152 |
+
) -> list["torch.Tensor"]:
|
| 153 |
+
"""Custom preprocessing for BEiT."""
|
| 154 |
+
if do_reduce_labels:
|
| 155 |
+
images = self.reduce_label(images)
|
| 156 |
+
|
| 157 |
+
# Group images by size for batched resizing
|
| 158 |
+
grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
|
| 159 |
+
resized_images_grouped = {}
|
| 160 |
+
for shape, stacked_images in grouped_images.items():
|
| 161 |
+
if do_resize:
|
| 162 |
+
stacked_images = self.resize(stacked_images, size, resample)
|
| 163 |
+
resized_images_grouped[shape] = stacked_images
|
| 164 |
+
resized_images = reorder_images(resized_images_grouped, grouped_images_index)
|
| 165 |
+
|
| 166 |
+
# Group images by size for further processing
|
| 167 |
+
grouped_images, grouped_images_index = group_images_by_shape(resized_images, disable_grouping=disable_grouping)
|
| 168 |
+
processed_images_grouped = {}
|
| 169 |
+
for shape, stacked_images in grouped_images.items():
|
| 170 |
+
if do_center_crop:
|
| 171 |
+
stacked_images = self.center_crop(stacked_images, crop_size)
|
| 172 |
+
# Use fused rescale and normalize
|
| 173 |
+
stacked_images = self.rescale_and_normalize(
|
| 174 |
+
stacked_images, do_rescale, rescale_factor, do_normalize, image_mean, image_std
|
| 175 |
+
)
|
| 176 |
+
processed_images_grouped[shape] = stacked_images
|
| 177 |
+
|
| 178 |
+
processed_images = reorder_images(processed_images_grouped, grouped_images_index)
|
| 179 |
+
|
| 180 |
+
return processed_images
|
| 181 |
+
|
| 182 |
+
def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple] | None = None):
|
| 183 |
+
"""
|
| 184 |
+
Converts the output of [`BeitForSemanticSegmentation`] into semantic segmentation maps.
|
| 185 |
+
|
| 186 |
+
Args:
|
| 187 |
+
outputs ([`BeitForSemanticSegmentation`]):
|
| 188 |
+
Raw outputs of the model.
|
| 189 |
+
target_sizes (`list[Tuple]` of length `batch_size`, *optional*):
|
| 190 |
+
List of tuples corresponding to the requested final size (height, width) of each prediction. If unset,
|
| 191 |
+
predictions will not be resized.
|
| 192 |
+
|
| 193 |
+
Returns:
|
| 194 |
+
semantic_segmentation: `list[torch.Tensor]` of length `batch_size`, where each item is a semantic
|
| 195 |
+
segmentation map of shape (height, width) corresponding to the target_sizes entry (if `target_sizes` is
|
| 196 |
+
specified). Each entry of each `torch.Tensor` correspond to a semantic class id.
|
| 197 |
+
"""
|
| 198 |
+
if not is_torch_available():
|
| 199 |
+
raise ImportError("PyTorch is required for post_process_semantic_segmentation")
|
| 200 |
+
|
| 201 |
+
logits = outputs.logits
|
| 202 |
+
|
| 203 |
+
# Resize logits and compute semantic segmentation maps
|
| 204 |
+
if target_sizes is not None:
|
| 205 |
+
if len(logits) != len(target_sizes):
|
| 206 |
+
raise ValueError(
|
| 207 |
+
"Make sure that you pass in as many target sizes as the batch dimension of the logits"
|
| 208 |
+
)
|
| 209 |
+
|
| 210 |
+
if isinstance(target_sizes, torch.Tensor):
|
| 211 |
+
target_sizes = target_sizes.numpy()
|
| 212 |
+
|
| 213 |
+
semantic_segmentation = []
|
| 214 |
+
|
| 215 |
+
for idx in range(len(logits)):
|
| 216 |
+
resized_logits = F.interpolate(
|
| 217 |
+
logits[idx].unsqueeze(dim=0), size=target_sizes[idx], mode="bilinear", align_corners=False
|
| 218 |
+
)
|
| 219 |
+
semantic_map = resized_logits[0].argmax(dim=0)
|
| 220 |
+
semantic_segmentation.append(semantic_map)
|
| 221 |
+
else:
|
| 222 |
+
semantic_segmentation = logits.argmax(dim=1)
|
| 223 |
+
semantic_segmentation = [semantic_segmentation[i] for i in range(semantic_segmentation.shape[0])]
|
| 224 |
+
|
| 225 |
+
return semantic_segmentation
|
| 226 |
+
|
| 227 |
+
|
| 228 |
+
__all__ = ["BeitImageProcessor"]
|
third_party/transformers/src/transformers/models/beit/image_processing_pil_beit.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Image processor class for BEiT."""
|
| 15 |
+
|
| 16 |
+
import numpy as np
|
| 17 |
+
|
| 18 |
+
from ...image_processing_backends import PilBackend
|
| 19 |
+
from ...image_processing_utils import BatchFeature
|
| 20 |
+
from ...image_utils import (
|
| 21 |
+
IMAGENET_STANDARD_MEAN,
|
| 22 |
+
IMAGENET_STANDARD_STD,
|
| 23 |
+
ChannelDimension,
|
| 24 |
+
ImageInput,
|
| 25 |
+
PILImageResampling,
|
| 26 |
+
SizeDict,
|
| 27 |
+
)
|
| 28 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 29 |
+
from ...utils import TensorType, auto_docstring
|
| 30 |
+
from ...utils.import_utils import requires
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# Adapted from transformers.models.beit.image_processing_beit.BeitImageProcessorKwargs
|
| 34 |
+
class BeitImageProcessorKwargs(ImagesKwargs, total=False):
|
| 35 |
+
r"""
|
| 36 |
+
do_reduce_labels (`bool`, *optional*, defaults to `self.do_reduce_labels`):
|
| 37 |
+
Whether or not to reduce all label values of segmentation maps by 1. Usually used for datasets where 0
|
| 38 |
+
is used for background, and background itself is not included in all classes of a dataset (e.g.
|
| 39 |
+
ADE20k). The background label will be replaced by 255.
|
| 40 |
+
"""
|
| 41 |
+
|
| 42 |
+
do_reduce_labels: bool
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
@auto_docstring
|
| 46 |
+
class BeitImageProcessorPil(PilBackend):
|
| 47 |
+
"""PIL backend for BEiT with reduce_label support."""
|
| 48 |
+
|
| 49 |
+
valid_kwargs = BeitImageProcessorKwargs
|
| 50 |
+
|
| 51 |
+
resample = PILImageResampling.BICUBIC
|
| 52 |
+
image_mean = IMAGENET_STANDARD_MEAN
|
| 53 |
+
image_std = IMAGENET_STANDARD_STD
|
| 54 |
+
size = {"height": 224, "width": 224}
|
| 55 |
+
default_to_square = True
|
| 56 |
+
crop_size = {"height": 224, "width": 224}
|
| 57 |
+
do_resize = True
|
| 58 |
+
do_center_crop = False
|
| 59 |
+
do_rescale = True
|
| 60 |
+
do_normalize = True
|
| 61 |
+
do_reduce_labels = False
|
| 62 |
+
|
| 63 |
+
def __init__(self, **kwargs: Unpack[BeitImageProcessorKwargs]):
|
| 64 |
+
super().__init__(**kwargs)
|
| 65 |
+
|
| 66 |
+
@auto_docstring
|
| 67 |
+
def preprocess(
|
| 68 |
+
self,
|
| 69 |
+
images: ImageInput,
|
| 70 |
+
segmentation_maps: ImageInput | None = None,
|
| 71 |
+
**kwargs: Unpack[BeitImageProcessorKwargs],
|
| 72 |
+
) -> BatchFeature:
|
| 73 |
+
r"""
|
| 74 |
+
segmentation_maps (`ImageInput`, *optional*):
|
| 75 |
+
The segmentation maps to preprocess.
|
| 76 |
+
"""
|
| 77 |
+
return super().preprocess(images, segmentation_maps, **kwargs)
|
| 78 |
+
|
| 79 |
+
def _preprocess_image_like_inputs(
|
| 80 |
+
self,
|
| 81 |
+
images: ImageInput,
|
| 82 |
+
segmentation_maps: ImageInput | None,
|
| 83 |
+
do_convert_rgb: bool,
|
| 84 |
+
input_data_format: ChannelDimension,
|
| 85 |
+
return_tensors: str | TensorType | None,
|
| 86 |
+
**kwargs,
|
| 87 |
+
) -> BatchFeature:
|
| 88 |
+
"""Handle extra inputs beyond images."""
|
| 89 |
+
images = self._prepare_image_like_inputs(
|
| 90 |
+
images=images, do_convert_rgb=do_convert_rgb, input_data_format=input_data_format
|
| 91 |
+
)
|
| 92 |
+
images_kwargs = kwargs.copy()
|
| 93 |
+
images_kwargs["do_reduce_labels"] = False
|
| 94 |
+
data = {}
|
| 95 |
+
data["pixel_values"] = self._preprocess(images, **images_kwargs)
|
| 96 |
+
|
| 97 |
+
# Prepare segmentation maps if provided
|
| 98 |
+
if segmentation_maps is not None:
|
| 99 |
+
processed_segmentation_maps = self._prepare_image_like_inputs(
|
| 100 |
+
images=segmentation_maps,
|
| 101 |
+
expected_ndims=2,
|
| 102 |
+
do_convert_rgb=False,
|
| 103 |
+
input_data_format=ChannelDimension.FIRST,
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
# Process segmentation maps with do_normalize=False and do_rescale=False
|
| 107 |
+
segmentation_maps_kwargs = kwargs.copy()
|
| 108 |
+
segmentation_maps_kwargs.update({"do_normalize": False, "do_rescale": False})
|
| 109 |
+
processed_segmentation_maps = self._preprocess(
|
| 110 |
+
images=processed_segmentation_maps, **segmentation_maps_kwargs
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
# Convert to int64 and squeeze channel dimension
|
| 114 |
+
data["labels"] = [
|
| 115 |
+
processed_segmentation_map.squeeze(0).astype(np.int64)
|
| 116 |
+
for processed_segmentation_map in processed_segmentation_maps
|
| 117 |
+
]
|
| 118 |
+
|
| 119 |
+
return BatchFeature(data=data, tensor_type=return_tensors)
|
| 120 |
+
|
| 121 |
+
def reduce_label(self, image: np.ndarray) -> np.ndarray:
|
| 122 |
+
"""Reduce label values by 1, replacing 0 with 255."""
|
| 123 |
+
# Avoid using underflow conversion
|
| 124 |
+
image[image == 0] = 255
|
| 125 |
+
image = image - 1
|
| 126 |
+
image[image == 254] = 255
|
| 127 |
+
return image
|
| 128 |
+
|
| 129 |
+
def _preprocess(
|
| 130 |
+
self,
|
| 131 |
+
images: list[np.ndarray],
|
| 132 |
+
do_resize: bool,
|
| 133 |
+
size: SizeDict,
|
| 134 |
+
resample: PILImageResampling | None,
|
| 135 |
+
do_center_crop: bool,
|
| 136 |
+
crop_size: SizeDict,
|
| 137 |
+
do_rescale: bool,
|
| 138 |
+
rescale_factor: float,
|
| 139 |
+
do_normalize: bool,
|
| 140 |
+
image_mean: float | list[float] | None,
|
| 141 |
+
image_std: float | list[float] | None,
|
| 142 |
+
do_reduce_labels: bool = False,
|
| 143 |
+
**kwargs,
|
| 144 |
+
) -> list[np.ndarray]:
|
| 145 |
+
"""Custom preprocessing for BEiT."""
|
| 146 |
+
processed_images = []
|
| 147 |
+
for image in images:
|
| 148 |
+
if do_reduce_labels:
|
| 149 |
+
image = self.reduce_label(image)
|
| 150 |
+
if do_resize:
|
| 151 |
+
image = self.resize(image, size, resample)
|
| 152 |
+
if do_center_crop:
|
| 153 |
+
image = self.center_crop(image, crop_size)
|
| 154 |
+
if do_rescale:
|
| 155 |
+
image = self.rescale(image, rescale_factor)
|
| 156 |
+
if do_normalize:
|
| 157 |
+
image = self.normalize(image, image_mean, image_std)
|
| 158 |
+
processed_images.append(image)
|
| 159 |
+
|
| 160 |
+
return processed_images
|
| 161 |
+
|
| 162 |
+
@requires(backends=("torch",))
|
| 163 |
+
def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple] | None = None):
|
| 164 |
+
"""
|
| 165 |
+
Converts the output of [`BeitForSemanticSegmentation`] into semantic segmentation maps.
|
| 166 |
+
|
| 167 |
+
Args:
|
| 168 |
+
outputs ([`BeitForSemanticSegmentation`]):
|
| 169 |
+
Raw outputs of the model.
|
| 170 |
+
target_sizes (`list[Tuple]` of length `batch_size`, *optional*):
|
| 171 |
+
List of tuples corresponding to the requested final size (height, width) of each prediction. If unset,
|
| 172 |
+
predictions will not be resized.
|
| 173 |
+
|
| 174 |
+
Returns:
|
| 175 |
+
semantic_segmentation: `list[torch.Tensor]` of length `batch_size`, where each item is a semantic
|
| 176 |
+
segmentation map of shape (height, width) corresponding to the target_sizes entry (if `target_sizes` is
|
| 177 |
+
specified). Each entry of each `torch.Tensor` correspond to a semantic class id.
|
| 178 |
+
"""
|
| 179 |
+
import torch
|
| 180 |
+
import torch.nn.functional as F
|
| 181 |
+
|
| 182 |
+
logits = outputs.logits
|
| 183 |
+
|
| 184 |
+
# Resize logits and compute semantic segmentation maps
|
| 185 |
+
if target_sizes is not None:
|
| 186 |
+
if len(logits) != len(target_sizes):
|
| 187 |
+
raise ValueError(
|
| 188 |
+
"Make sure that you pass in as many target sizes as the batch dimension of the logits"
|
| 189 |
+
)
|
| 190 |
+
|
| 191 |
+
if isinstance(target_sizes, torch.Tensor):
|
| 192 |
+
target_sizes = target_sizes.numpy()
|
| 193 |
+
|
| 194 |
+
semantic_segmentation = []
|
| 195 |
+
|
| 196 |
+
for idx in range(len(logits)):
|
| 197 |
+
resized_logits = F.interpolate(
|
| 198 |
+
logits[idx].unsqueeze(dim=0), size=target_sizes[idx], mode="bilinear", align_corners=False
|
| 199 |
+
)
|
| 200 |
+
semantic_map = resized_logits[0].argmax(dim=0)
|
| 201 |
+
semantic_segmentation.append(semantic_map)
|
| 202 |
+
else:
|
| 203 |
+
semantic_segmentation = logits.argmax(dim=1)
|
| 204 |
+
semantic_segmentation = [semantic_segmentation[i] for i in range(semantic_segmentation.shape[0])]
|
| 205 |
+
|
| 206 |
+
return semantic_segmentation
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
__all__ = ["BeitImageProcessorPil"]
|
third_party/transformers/src/transformers/models/beit/modeling_beit.py
ADDED
|
@@ -0,0 +1,1470 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 Microsoft Research and The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch BEiT model."""
|
| 15 |
+
|
| 16 |
+
import collections.abc
|
| 17 |
+
import math
|
| 18 |
+
from dataclasses import dataclass
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
from torch import Tensor, nn
|
| 22 |
+
from torch.nn import CrossEntropyLoss
|
| 23 |
+
|
| 24 |
+
from ... import initialization as init
|
| 25 |
+
from ...activations import ACT2FN
|
| 26 |
+
from ...backbone_utils import BackboneMixin, filter_output_hidden_states
|
| 27 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 28 |
+
from ...modeling_outputs import (
|
| 29 |
+
BackboneOutput,
|
| 30 |
+
BaseModelOutput,
|
| 31 |
+
BaseModelOutputWithPooling,
|
| 32 |
+
ImageClassifierOutput,
|
| 33 |
+
MaskedLMOutput,
|
| 34 |
+
SemanticSegmenterOutput,
|
| 35 |
+
)
|
| 36 |
+
from ...modeling_utils import PreTrainedModel
|
| 37 |
+
from ...pytorch_utils import compile_compatible_method_lru_cache
|
| 38 |
+
from ...utils import auto_docstring, logging, torch_int
|
| 39 |
+
from ...utils.generic import can_return_tuple
|
| 40 |
+
from .configuration_beit import BeitConfig
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
logger = logging.get_logger(__name__)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
@dataclass
|
| 47 |
+
@auto_docstring(
|
| 48 |
+
custom_intro="""
|
| 49 |
+
Class for outputs of [`BeitModel`].
|
| 50 |
+
"""
|
| 51 |
+
)
|
| 52 |
+
class BeitModelOutputWithPooling(BaseModelOutputWithPooling):
|
| 53 |
+
r"""
|
| 54 |
+
pooler_output (`torch.FloatTensor` of shape `(batch_size, hidden_size)`):
|
| 55 |
+
Average of the last layer hidden states of the patch tokens (excluding the *[CLS]* token) if
|
| 56 |
+
*config.use_mean_pooling* is set to True. If set to False, then the final hidden state of the *[CLS]* token
|
| 57 |
+
will be returned.
|
| 58 |
+
"""
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def drop_path(input: torch.Tensor, drop_prob: float = 0.0, training: bool = False) -> torch.Tensor:
|
| 62 |
+
"""
|
| 63 |
+
Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).
|
| 64 |
+
|
| 65 |
+
"""
|
| 66 |
+
if drop_prob == 0.0 or not training:
|
| 67 |
+
return input
|
| 68 |
+
keep_prob = 1 - drop_prob
|
| 69 |
+
shape = (input.shape[0],) + (1,) * (input.ndim - 1) # work with diff dim tensors, not just 2D ConvNets
|
| 70 |
+
random_tensor = keep_prob + torch.rand(shape, dtype=input.dtype, device=input.device)
|
| 71 |
+
random_tensor.floor_() # binarize
|
| 72 |
+
output = input.div(keep_prob) * random_tensor
|
| 73 |
+
return output
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
class BeitDropPath(nn.Module):
|
| 77 |
+
"""Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks)."""
|
| 78 |
+
|
| 79 |
+
def __init__(self, drop_prob: float | None = None) -> None:
|
| 80 |
+
super().__init__()
|
| 81 |
+
self.drop_prob = drop_prob
|
| 82 |
+
|
| 83 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 84 |
+
return drop_path(hidden_states, self.drop_prob, self.training)
|
| 85 |
+
|
| 86 |
+
def extra_repr(self) -> str:
|
| 87 |
+
return f"p={self.drop_prob}"
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
# Based on timm implementation, which can be found here:
|
| 91 |
+
# https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/vision_transformer.py
|
| 92 |
+
class BeitEmbeddings(nn.Module):
|
| 93 |
+
"""
|
| 94 |
+
Construct the CLS token, position and patch embeddings. Optionally, also the mask token.
|
| 95 |
+
|
| 96 |
+
"""
|
| 97 |
+
|
| 98 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 99 |
+
super().__init__()
|
| 100 |
+
|
| 101 |
+
self.cls_token = nn.Parameter(torch.zeros(1, 1, config.hidden_size))
|
| 102 |
+
if config.use_mask_token:
|
| 103 |
+
self.mask_token = nn.Parameter(torch.zeros(1, 1, config.hidden_size))
|
| 104 |
+
else:
|
| 105 |
+
self.mask_token = None
|
| 106 |
+
self.patch_embeddings = BeitPatchEmbeddings(config)
|
| 107 |
+
self.patch_size = config.patch_size
|
| 108 |
+
self.image_size = (
|
| 109 |
+
config.image_size
|
| 110 |
+
if isinstance(config.image_size, collections.abc.Iterable)
|
| 111 |
+
else (config.image_size, config.image_size)
|
| 112 |
+
)
|
| 113 |
+
num_patches = self.patch_embeddings.num_patches
|
| 114 |
+
if config.use_absolute_position_embeddings:
|
| 115 |
+
self.position_embeddings = nn.Parameter(torch.zeros(1, num_patches + 1, config.hidden_size))
|
| 116 |
+
else:
|
| 117 |
+
self.position_embeddings = None
|
| 118 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 119 |
+
|
| 120 |
+
# Copied from transformers.models.vit.modeling_vit.ViTEmbeddings.interpolate_pos_encoding
|
| 121 |
+
def interpolate_pos_encoding(self, embeddings: torch.Tensor, height: int, width: int) -> torch.Tensor:
|
| 122 |
+
"""
|
| 123 |
+
This method allows to interpolate the pre-trained position encodings, to be able to use the model on higher resolution
|
| 124 |
+
images. This method is also adapted to support torch.jit tracing.
|
| 125 |
+
|
| 126 |
+
Adapted from:
|
| 127 |
+
- https://github.com/facebookresearch/dino/blob/de9ee3df6cf39fac952ab558447af1fa1365362a/vision_transformer.py#L174-L194, and
|
| 128 |
+
- https://github.com/facebookresearch/dinov2/blob/e1277af2ba9496fbadf7aec6eba56e8d882d1e35/dinov2/models/vision_transformer.py#L179-L211
|
| 129 |
+
"""
|
| 130 |
+
|
| 131 |
+
num_patches = embeddings.shape[1] - 1
|
| 132 |
+
num_positions = self.position_embeddings.shape[1] - 1
|
| 133 |
+
|
| 134 |
+
# always interpolate when tracing to ensure the exported model works for dynamic input shapes
|
| 135 |
+
if not torch.jit.is_tracing() and num_patches == num_positions and height == width:
|
| 136 |
+
return self.position_embeddings
|
| 137 |
+
|
| 138 |
+
class_pos_embed = self.position_embeddings[:, :1]
|
| 139 |
+
patch_pos_embed = self.position_embeddings[:, 1:]
|
| 140 |
+
|
| 141 |
+
dim = embeddings.shape[-1]
|
| 142 |
+
|
| 143 |
+
new_height = height // self.patch_size
|
| 144 |
+
new_width = width // self.patch_size
|
| 145 |
+
|
| 146 |
+
sqrt_num_positions = torch_int(num_positions**0.5)
|
| 147 |
+
patch_pos_embed = patch_pos_embed.reshape(1, sqrt_num_positions, sqrt_num_positions, dim)
|
| 148 |
+
patch_pos_embed = patch_pos_embed.permute(0, 3, 1, 2)
|
| 149 |
+
|
| 150 |
+
patch_pos_embed = nn.functional.interpolate(
|
| 151 |
+
patch_pos_embed,
|
| 152 |
+
size=(new_height, new_width),
|
| 153 |
+
mode="bicubic",
|
| 154 |
+
align_corners=False,
|
| 155 |
+
)
|
| 156 |
+
|
| 157 |
+
patch_pos_embed = patch_pos_embed.permute(0, 2, 3, 1).view(1, -1, dim)
|
| 158 |
+
|
| 159 |
+
return torch.cat((class_pos_embed, patch_pos_embed), dim=1)
|
| 160 |
+
|
| 161 |
+
def forward(
|
| 162 |
+
self,
|
| 163 |
+
pixel_values: torch.Tensor,
|
| 164 |
+
bool_masked_pos: torch.BoolTensor | None = None,
|
| 165 |
+
) -> torch.Tensor:
|
| 166 |
+
_, _, height, width = pixel_values.shape
|
| 167 |
+
embeddings, (patch_height, patch_width) = self.patch_embeddings(pixel_values)
|
| 168 |
+
batch_size, seq_len, _ = embeddings.size()
|
| 169 |
+
|
| 170 |
+
if bool_masked_pos is not None:
|
| 171 |
+
mask_tokens = self.mask_token.expand(batch_size, seq_len, -1)
|
| 172 |
+
# replace the masked visual tokens by mask_tokens
|
| 173 |
+
w = bool_masked_pos.unsqueeze(-1).type_as(mask_tokens)
|
| 174 |
+
embeddings = embeddings * (1 - w) + mask_tokens * w
|
| 175 |
+
|
| 176 |
+
cls_tokens = self.cls_token.expand(batch_size, -1, -1)
|
| 177 |
+
embeddings = torch.cat((cls_tokens, embeddings), dim=1)
|
| 178 |
+
|
| 179 |
+
if self.position_embeddings is not None:
|
| 180 |
+
embeddings = embeddings + self.interpolate_pos_encoding(embeddings, height, width)
|
| 181 |
+
|
| 182 |
+
embeddings = self.dropout(embeddings)
|
| 183 |
+
|
| 184 |
+
return embeddings, (patch_height, patch_width)
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
class BeitPatchEmbeddings(nn.Module):
|
| 188 |
+
"""
|
| 189 |
+
This class turns `pixel_values` of shape `(batch_size, num_channels, height, width)` into the initial
|
| 190 |
+
`hidden_states` (patch embeddings) of shape `(batch_size, seq_length, hidden_size)` to be consumed by a
|
| 191 |
+
Transformer.
|
| 192 |
+
"""
|
| 193 |
+
|
| 194 |
+
def __init__(self, config):
|
| 195 |
+
super().__init__()
|
| 196 |
+
image_size, patch_size = config.image_size, config.patch_size
|
| 197 |
+
num_channels, hidden_size = config.num_channels, config.hidden_size
|
| 198 |
+
|
| 199 |
+
image_size = image_size if isinstance(image_size, collections.abc.Iterable) else (image_size, image_size)
|
| 200 |
+
patch_size = patch_size if isinstance(patch_size, collections.abc.Iterable) else (patch_size, patch_size)
|
| 201 |
+
num_patches = (image_size[1] // patch_size[1]) * (image_size[0] // patch_size[0])
|
| 202 |
+
patch_shape = (image_size[0] // patch_size[0], image_size[1] // patch_size[1])
|
| 203 |
+
self.image_size = image_size
|
| 204 |
+
self.patch_size = patch_size
|
| 205 |
+
self.num_channels = num_channels
|
| 206 |
+
self.num_patches = num_patches
|
| 207 |
+
self.patch_shape = patch_shape
|
| 208 |
+
|
| 209 |
+
self.projection = nn.Conv2d(num_channels, hidden_size, kernel_size=patch_size, stride=patch_size)
|
| 210 |
+
|
| 211 |
+
def forward(self, pixel_values: torch.Tensor) -> torch.Tensor:
|
| 212 |
+
batch_size, num_channels, height, width = pixel_values.shape
|
| 213 |
+
if num_channels != self.num_channels:
|
| 214 |
+
raise ValueError(
|
| 215 |
+
"Make sure that the channel dimension of the pixel values match with the one set in the configuration."
|
| 216 |
+
)
|
| 217 |
+
|
| 218 |
+
embeddings = self.projection(pixel_values.to(self.projection.weight.dtype))
|
| 219 |
+
patch_height, patch_width = embeddings.shape[2], embeddings.shape[3]
|
| 220 |
+
embeddings = embeddings.flatten(2).transpose(1, 2)
|
| 221 |
+
|
| 222 |
+
return embeddings, (patch_height, patch_width)
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
class BeitSelfAttention(nn.Module):
|
| 226 |
+
def __init__(self, config: BeitConfig, window_size: tuple | None = None) -> None:
|
| 227 |
+
super().__init__()
|
| 228 |
+
self.config = config
|
| 229 |
+
if config.hidden_size % config.num_attention_heads != 0 and not hasattr(config, "embedding_size"):
|
| 230 |
+
raise ValueError(
|
| 231 |
+
f"The hidden size {config.hidden_size} is not a multiple of the number of attention "
|
| 232 |
+
f"heads {config.num_attention_heads}."
|
| 233 |
+
)
|
| 234 |
+
|
| 235 |
+
self.num_attention_heads = config.num_attention_heads
|
| 236 |
+
self.attention_head_size = int(config.hidden_size / config.num_attention_heads)
|
| 237 |
+
self.all_head_size = self.num_attention_heads * self.attention_head_size
|
| 238 |
+
|
| 239 |
+
self.query = nn.Linear(config.hidden_size, self.all_head_size)
|
| 240 |
+
self.key = nn.Linear(config.hidden_size, self.all_head_size, bias=False)
|
| 241 |
+
self.value = nn.Linear(config.hidden_size, self.all_head_size)
|
| 242 |
+
|
| 243 |
+
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
|
| 244 |
+
|
| 245 |
+
self.has_relative_position_bias = bool(window_size)
|
| 246 |
+
if self.has_relative_position_bias:
|
| 247 |
+
self.relative_position_bias = BeitRelativePositionBias(config, window_size=window_size)
|
| 248 |
+
|
| 249 |
+
def forward(
|
| 250 |
+
self,
|
| 251 |
+
hidden_states: torch.Tensor,
|
| 252 |
+
output_attentions: bool = False,
|
| 253 |
+
relative_position_bias: torch.Tensor | None = None,
|
| 254 |
+
interpolate_pos_encoding: bool = False,
|
| 255 |
+
resolution: tuple[int] | None = None,
|
| 256 |
+
) -> tuple[torch.Tensor] | tuple[torch.Tensor, torch.Tensor]:
|
| 257 |
+
batch_size, seq_length, _ = hidden_states.shape
|
| 258 |
+
query_layer = (
|
| 259 |
+
self.query(hidden_states)
|
| 260 |
+
.view(batch_size, -1, self.num_attention_heads, self.attention_head_size)
|
| 261 |
+
.transpose(1, 2)
|
| 262 |
+
)
|
| 263 |
+
key_layer = (
|
| 264 |
+
self.key(hidden_states)
|
| 265 |
+
.view(batch_size, -1, self.num_attention_heads, self.attention_head_size)
|
| 266 |
+
.transpose(1, 2)
|
| 267 |
+
)
|
| 268 |
+
value_layer = (
|
| 269 |
+
self.value(hidden_states)
|
| 270 |
+
.view(batch_size, -1, self.num_attention_heads, self.attention_head_size)
|
| 271 |
+
.transpose(1, 2)
|
| 272 |
+
)
|
| 273 |
+
|
| 274 |
+
# Take the dot product between "query" and "key" to get the raw attention scores.
|
| 275 |
+
attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2))
|
| 276 |
+
|
| 277 |
+
attention_scores = attention_scores / math.sqrt(self.attention_head_size)
|
| 278 |
+
|
| 279 |
+
# Add relative position bias if present.
|
| 280 |
+
if self.has_relative_position_bias:
|
| 281 |
+
height, width = resolution
|
| 282 |
+
window_size = (height // self.config.patch_size, width // self.config.patch_size)
|
| 283 |
+
attention_scores = attention_scores + self.relative_position_bias(
|
| 284 |
+
window_size, interpolate_pos_encoding, dim_size=hidden_states.shape[1]
|
| 285 |
+
)
|
| 286 |
+
|
| 287 |
+
# Add shared relative position bias if provided.
|
| 288 |
+
if relative_position_bias is not None:
|
| 289 |
+
attention_scores = attention_scores + relative_position_bias
|
| 290 |
+
|
| 291 |
+
# Normalize the attention scores to probabilities.
|
| 292 |
+
attention_probs = nn.functional.softmax(attention_scores, dim=-1)
|
| 293 |
+
|
| 294 |
+
# This is actually dropping out entire tokens to attend to, which might
|
| 295 |
+
# seem a bit unusual, but is taken from the original Transformer paper.
|
| 296 |
+
attention_probs = self.dropout(attention_probs)
|
| 297 |
+
|
| 298 |
+
context_layer = torch.matmul(attention_probs, value_layer)
|
| 299 |
+
|
| 300 |
+
context_layer = context_layer.permute(0, 2, 1, 3).contiguous()
|
| 301 |
+
new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,)
|
| 302 |
+
context_layer = context_layer.view(*new_context_layer_shape)
|
| 303 |
+
|
| 304 |
+
outputs = (context_layer, attention_probs) if output_attentions else (context_layer,)
|
| 305 |
+
|
| 306 |
+
return outputs
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
class BeitSdpaSelfAttention(BeitSelfAttention):
|
| 310 |
+
def forward(
|
| 311 |
+
self,
|
| 312 |
+
hidden_states: torch.Tensor,
|
| 313 |
+
output_attentions: bool = False,
|
| 314 |
+
relative_position_bias: torch.Tensor | None = None,
|
| 315 |
+
interpolate_pos_encoding: bool = False,
|
| 316 |
+
resolution: tuple[int] | None = None,
|
| 317 |
+
) -> tuple[torch.Tensor] | tuple[torch.Tensor, torch.Tensor]:
|
| 318 |
+
if output_attentions:
|
| 319 |
+
logger.warning_once(
|
| 320 |
+
f"{self.__class__.__name__} does not support `output_attentions=True`. The returned attention weights will "
|
| 321 |
+
"be `None`. If you want to get attention weights, please set `attn_implementation='eager'` when loading the model."
|
| 322 |
+
)
|
| 323 |
+
batch_size, seq_length, _ = hidden_states.shape
|
| 324 |
+
query_layer = (
|
| 325 |
+
self.query(hidden_states)
|
| 326 |
+
.view(batch_size, -1, self.num_attention_heads, self.attention_head_size)
|
| 327 |
+
.transpose(1, 2)
|
| 328 |
+
)
|
| 329 |
+
key_layer = (
|
| 330 |
+
self.key(hidden_states)
|
| 331 |
+
.view(batch_size, -1, self.num_attention_heads, self.attention_head_size)
|
| 332 |
+
.transpose(1, 2)
|
| 333 |
+
)
|
| 334 |
+
value_layer = (
|
| 335 |
+
self.value(hidden_states)
|
| 336 |
+
.view(batch_size, -1, self.num_attention_heads, self.attention_head_size)
|
| 337 |
+
.transpose(1, 2)
|
| 338 |
+
)
|
| 339 |
+
|
| 340 |
+
attn_bias = None
|
| 341 |
+
if self.has_relative_position_bias:
|
| 342 |
+
height, width = resolution
|
| 343 |
+
window_size = (height // self.config.patch_size, width // self.config.patch_size)
|
| 344 |
+
attn_bias = self.relative_position_bias(
|
| 345 |
+
window_size, interpolate_pos_encoding, dim_size=hidden_states.shape[1]
|
| 346 |
+
)
|
| 347 |
+
|
| 348 |
+
# Add shared relative position bias if provided.
|
| 349 |
+
if relative_position_bias is not None:
|
| 350 |
+
if attn_bias is None:
|
| 351 |
+
attn_bias = relative_position_bias
|
| 352 |
+
else:
|
| 353 |
+
attn_bias += relative_position_bias
|
| 354 |
+
|
| 355 |
+
scaling = 1 / math.sqrt(self.attention_head_size)
|
| 356 |
+
context_layer = torch.nn.functional.scaled_dot_product_attention(
|
| 357 |
+
query_layer,
|
| 358 |
+
key_layer,
|
| 359 |
+
value_layer,
|
| 360 |
+
attn_mask=attn_bias,
|
| 361 |
+
dropout_p=self.config.attention_probs_dropout_prob if self.training else 0.0,
|
| 362 |
+
is_causal=False,
|
| 363 |
+
scale=scaling,
|
| 364 |
+
)
|
| 365 |
+
context_layer = context_layer.permute(0, 2, 1, 3).contiguous()
|
| 366 |
+
new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,)
|
| 367 |
+
context_layer = context_layer.view(*new_context_layer_shape)
|
| 368 |
+
return context_layer, None
|
| 369 |
+
|
| 370 |
+
|
| 371 |
+
class BeitSelfOutput(nn.Module):
|
| 372 |
+
"""
|
| 373 |
+
The residual connection is defined in BeitLayer instead of here (as is the case with other models), due to the
|
| 374 |
+
layernorm applied before each block.
|
| 375 |
+
"""
|
| 376 |
+
|
| 377 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 378 |
+
super().__init__()
|
| 379 |
+
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
|
| 380 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 381 |
+
|
| 382 |
+
def forward(self, hidden_states: torch.Tensor, input_tensor: torch.Tensor, gamma=None) -> torch.Tensor:
|
| 383 |
+
hidden_states = self.dense(hidden_states)
|
| 384 |
+
hidden_states = self.dropout(hidden_states)
|
| 385 |
+
|
| 386 |
+
return hidden_states
|
| 387 |
+
|
| 388 |
+
|
| 389 |
+
BEIT_SELF_ATTENTION_CLASSES = {
|
| 390 |
+
"eager": BeitSelfAttention,
|
| 391 |
+
"sdpa": BeitSdpaSelfAttention,
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
class BeitAttention(nn.Module):
|
| 396 |
+
def __init__(self, config: BeitConfig, window_size: tuple | None = None) -> None:
|
| 397 |
+
super().__init__()
|
| 398 |
+
self.attention = BEIT_SELF_ATTENTION_CLASSES[config._attn_implementation](config, window_size=window_size)
|
| 399 |
+
self.output = BeitSelfOutput(config)
|
| 400 |
+
|
| 401 |
+
def forward(
|
| 402 |
+
self,
|
| 403 |
+
hidden_states: torch.Tensor,
|
| 404 |
+
output_attentions: bool = False,
|
| 405 |
+
relative_position_bias: torch.Tensor | None = None,
|
| 406 |
+
interpolate_pos_encoding: bool = False,
|
| 407 |
+
resolution: tuple[int] | None = None,
|
| 408 |
+
) -> tuple[torch.Tensor] | tuple[torch.Tensor, torch.Tensor]:
|
| 409 |
+
self_outputs = self.attention(
|
| 410 |
+
hidden_states, output_attentions, relative_position_bias, interpolate_pos_encoding, resolution
|
| 411 |
+
)
|
| 412 |
+
|
| 413 |
+
attention_output = self.output(self_outputs[0], hidden_states)
|
| 414 |
+
|
| 415 |
+
outputs = (attention_output,) + self_outputs[1:] # add attentions if we output them
|
| 416 |
+
return outputs
|
| 417 |
+
|
| 418 |
+
|
| 419 |
+
class BeitIntermediate(nn.Module):
|
| 420 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 421 |
+
super().__init__()
|
| 422 |
+
self.dense = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 423 |
+
if isinstance(config.hidden_act, str):
|
| 424 |
+
self.intermediate_act_fn = ACT2FN[config.hidden_act]
|
| 425 |
+
else:
|
| 426 |
+
self.intermediate_act_fn = config.hidden_act
|
| 427 |
+
|
| 428 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 429 |
+
hidden_states = self.dense(hidden_states)
|
| 430 |
+
hidden_states = self.intermediate_act_fn(hidden_states)
|
| 431 |
+
|
| 432 |
+
return hidden_states
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
class BeitOutput(nn.Module):
|
| 436 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 437 |
+
super().__init__()
|
| 438 |
+
self.dense = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 439 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 440 |
+
|
| 441 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 442 |
+
hidden_states = self.dense(hidden_states)
|
| 443 |
+
hidden_states = self.dropout(hidden_states)
|
| 444 |
+
|
| 445 |
+
return hidden_states
|
| 446 |
+
|
| 447 |
+
|
| 448 |
+
class BeitLayer(GradientCheckpointingLayer):
|
| 449 |
+
"""This corresponds to the Block class in the timm implementation."""
|
| 450 |
+
|
| 451 |
+
def __init__(self, config: BeitConfig, window_size: tuple | None = None, drop_path_rate: float = 0.0) -> None:
|
| 452 |
+
super().__init__()
|
| 453 |
+
self.chunk_size_feed_forward = config.chunk_size_feed_forward
|
| 454 |
+
self.seq_len_dim = 1
|
| 455 |
+
self.attention = BeitAttention(config, window_size=window_size)
|
| 456 |
+
self.intermediate = BeitIntermediate(config)
|
| 457 |
+
self.output = BeitOutput(config)
|
| 458 |
+
self.layernorm_before = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 459 |
+
self.drop_path = BeitDropPath(drop_path_rate) if drop_path_rate > 0.0 else nn.Identity()
|
| 460 |
+
self.layernorm_after = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 461 |
+
|
| 462 |
+
init_values = config.layer_scale_init_value
|
| 463 |
+
if init_values > 0:
|
| 464 |
+
self.lambda_1 = nn.Parameter(init_values * torch.ones(config.hidden_size), requires_grad=True)
|
| 465 |
+
self.lambda_2 = nn.Parameter(init_values * torch.ones(config.hidden_size), requires_grad=True)
|
| 466 |
+
else:
|
| 467 |
+
self.lambda_1, self.lambda_2 = None, None
|
| 468 |
+
|
| 469 |
+
def forward(
|
| 470 |
+
self,
|
| 471 |
+
hidden_states: torch.Tensor,
|
| 472 |
+
output_attentions: bool = False,
|
| 473 |
+
relative_position_bias: torch.Tensor | None = None,
|
| 474 |
+
interpolate_pos_encoding: bool = False,
|
| 475 |
+
resolution: tuple[int, int] | None = None,
|
| 476 |
+
) -> tuple[torch.Tensor] | tuple[torch.Tensor, torch.Tensor]:
|
| 477 |
+
self_attention_outputs = self.attention(
|
| 478 |
+
self.layernorm_before(hidden_states), # in BEiT, layernorm is applied before self-attention
|
| 479 |
+
output_attentions=output_attentions,
|
| 480 |
+
relative_position_bias=relative_position_bias,
|
| 481 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 482 |
+
resolution=resolution,
|
| 483 |
+
)
|
| 484 |
+
attention_output = self_attention_outputs[0]
|
| 485 |
+
outputs = self_attention_outputs[1:] # add self attentions if we output attention weights
|
| 486 |
+
|
| 487 |
+
# apply lambda_1 if present
|
| 488 |
+
if self.lambda_1 is not None:
|
| 489 |
+
attention_output = self.lambda_1 * attention_output
|
| 490 |
+
|
| 491 |
+
# first residual connection
|
| 492 |
+
hidden_states = self.drop_path(attention_output) + hidden_states
|
| 493 |
+
|
| 494 |
+
# in BEiT, layernorm is also applied after self-attention
|
| 495 |
+
layer_output = self.layernorm_after(hidden_states)
|
| 496 |
+
|
| 497 |
+
layer_output = self.intermediate(layer_output)
|
| 498 |
+
layer_output = self.output(layer_output)
|
| 499 |
+
|
| 500 |
+
if self.lambda_2 is not None:
|
| 501 |
+
layer_output = self.lambda_2 * layer_output
|
| 502 |
+
|
| 503 |
+
# second residual connection
|
| 504 |
+
layer_output = self.drop_path(layer_output) + hidden_states
|
| 505 |
+
|
| 506 |
+
outputs = (layer_output,) + outputs
|
| 507 |
+
|
| 508 |
+
return outputs
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
class BeitRelativePositionBias(nn.Module):
|
| 512 |
+
def __init__(self, config: BeitConfig, window_size: tuple) -> None:
|
| 513 |
+
super().__init__()
|
| 514 |
+
self.window_size = window_size
|
| 515 |
+
self.num_relative_distance = (2 * window_size[0] - 1) * (2 * window_size[1] - 1) + 3
|
| 516 |
+
self.relative_position_bias_table = nn.Parameter(
|
| 517 |
+
torch.zeros(self.num_relative_distance, config.num_attention_heads)
|
| 518 |
+
) # 2*Wh-1 * 2*Ww-1, nH
|
| 519 |
+
# cls to token & token 2 cls & cls to cls
|
| 520 |
+
|
| 521 |
+
@compile_compatible_method_lru_cache(maxsize=10)
|
| 522 |
+
def generate_relative_position_index(self, window_size: tuple[int, int]) -> torch.Tensor:
|
| 523 |
+
"""
|
| 524 |
+
This method creates the relative position index, modified to support arbitrary window sizes,
|
| 525 |
+
as introduced in [MiDaS v3.1](https://huggingface.co/papers/2307.14460).
|
| 526 |
+
"""
|
| 527 |
+
num_relative_distance = (2 * window_size[0] - 1) * (2 * window_size[1] - 1) + 3
|
| 528 |
+
# cls to token & token 2 cls & cls to cls
|
| 529 |
+
# get pair-wise relative position index for each token inside the window
|
| 530 |
+
window_area = window_size[0] * window_size[1]
|
| 531 |
+
grid = torch.meshgrid(torch.arange(window_size[0]), torch.arange(window_size[1]), indexing="ij")
|
| 532 |
+
coords = torch.stack(grid) # 2, Wh, Ww
|
| 533 |
+
coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww
|
| 534 |
+
relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww
|
| 535 |
+
relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2
|
| 536 |
+
relative_coords[:, :, 0] += window_size[0] - 1 # shift to start from 0
|
| 537 |
+
relative_coords[:, :, 1] += window_size[1] - 1
|
| 538 |
+
relative_coords[:, :, 0] *= 2 * window_size[1] - 1
|
| 539 |
+
relative_position_index = torch.zeros(size=(window_area + 1,) * 2, dtype=relative_coords.dtype)
|
| 540 |
+
relative_position_index[1:, 1:] = relative_coords.sum(-1) # Wh*Ww, Wh*Ww
|
| 541 |
+
relative_position_index[0, 0:] = num_relative_distance - 3
|
| 542 |
+
relative_position_index[0:, 0] = num_relative_distance - 2
|
| 543 |
+
relative_position_index[0, 0] = num_relative_distance - 1
|
| 544 |
+
return relative_position_index
|
| 545 |
+
|
| 546 |
+
def forward(self, window_size, interpolate_pos_encoding: bool = False, dim_size=None) -> torch.Tensor:
|
| 547 |
+
"""
|
| 548 |
+
Modification of timm.models.beit.py: Attention._get_rel_pos_bias to support arbitrary window sizes.
|
| 549 |
+
"""
|
| 550 |
+
old_height = 2 * self.window_size[0] - 1
|
| 551 |
+
old_width = 2 * self.window_size[1] - 1
|
| 552 |
+
|
| 553 |
+
new_height = 2 * window_size[0] - 1
|
| 554 |
+
new_width = 2 * window_size[1] - 1
|
| 555 |
+
|
| 556 |
+
old_relative_position_bias_table = self.relative_position_bias_table
|
| 557 |
+
|
| 558 |
+
old_num_relative_distance = self.num_relative_distance
|
| 559 |
+
new_num_relative_distance = new_height * new_width + 3
|
| 560 |
+
|
| 561 |
+
old_sub_table = old_relative_position_bias_table[: old_num_relative_distance - 3]
|
| 562 |
+
|
| 563 |
+
old_sub_table = old_sub_table.reshape(1, old_width, old_height, -1).permute(0, 3, 1, 2)
|
| 564 |
+
new_sub_table = nn.functional.interpolate(
|
| 565 |
+
old_sub_table, size=(torch_int(new_height), torch_int(new_width)), mode="bilinear"
|
| 566 |
+
)
|
| 567 |
+
new_sub_table = new_sub_table.permute(0, 2, 3, 1).reshape(new_num_relative_distance - 3, -1)
|
| 568 |
+
|
| 569 |
+
new_relative_position_bias_table = torch.cat(
|
| 570 |
+
[new_sub_table, old_relative_position_bias_table[old_num_relative_distance - 3 :]]
|
| 571 |
+
)
|
| 572 |
+
|
| 573 |
+
relative_position_index = self.generate_relative_position_index(window_size)
|
| 574 |
+
relative_position_bias = new_relative_position_bias_table[relative_position_index.view(-1)]
|
| 575 |
+
|
| 576 |
+
# patch_size*num_patches_height, patch_size*num_patches_width, num_attention_heads
|
| 577 |
+
relative_position_bias = relative_position_bias.view(
|
| 578 |
+
window_size[0] * window_size[1] + 1, window_size[0] * window_size[1] + 1, -1
|
| 579 |
+
)
|
| 580 |
+
# num_attention_heads, patch_size*num_patches_width, patch_size*num_patches_height
|
| 581 |
+
relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()
|
| 582 |
+
|
| 583 |
+
if interpolate_pos_encoding:
|
| 584 |
+
relative_position_bias = nn.functional.interpolate(
|
| 585 |
+
relative_position_bias.unsqueeze(1),
|
| 586 |
+
size=(dim_size, dim_size),
|
| 587 |
+
mode="bilinear",
|
| 588 |
+
align_corners=False,
|
| 589 |
+
).squeeze(1)
|
| 590 |
+
|
| 591 |
+
return relative_position_bias.unsqueeze(0)
|
| 592 |
+
|
| 593 |
+
|
| 594 |
+
class BeitEncoder(nn.Module):
|
| 595 |
+
def __init__(self, config: BeitConfig, window_size: tuple | None = None) -> None:
|
| 596 |
+
super().__init__()
|
| 597 |
+
self.config = config
|
| 598 |
+
self.has_relative_position_bias = config.use_shared_relative_position_bias
|
| 599 |
+
if self.has_relative_position_bias:
|
| 600 |
+
self.relative_position_bias = BeitRelativePositionBias(config, window_size=window_size)
|
| 601 |
+
|
| 602 |
+
# stochastic depth decay rule
|
| 603 |
+
dpr = [x.item() for x in torch.linspace(0, config.drop_path_rate, config.num_hidden_layers, device="cpu")]
|
| 604 |
+
self.layer = nn.ModuleList(
|
| 605 |
+
[
|
| 606 |
+
BeitLayer(
|
| 607 |
+
config,
|
| 608 |
+
window_size=window_size if config.use_relative_position_bias else None,
|
| 609 |
+
drop_path_rate=dpr[i],
|
| 610 |
+
)
|
| 611 |
+
for i in range(config.num_hidden_layers)
|
| 612 |
+
]
|
| 613 |
+
)
|
| 614 |
+
self.gradient_checkpointing = False
|
| 615 |
+
|
| 616 |
+
def forward(
|
| 617 |
+
self,
|
| 618 |
+
hidden_states: torch.Tensor,
|
| 619 |
+
output_attentions: bool = False,
|
| 620 |
+
output_hidden_states: bool = False,
|
| 621 |
+
interpolate_pos_encoding: bool = False,
|
| 622 |
+
resolution: tuple[int, int] | None = None,
|
| 623 |
+
return_dict: bool = True,
|
| 624 |
+
) -> tuple | BaseModelOutput:
|
| 625 |
+
all_hidden_states = () if output_hidden_states else None
|
| 626 |
+
all_self_attentions = () if output_attentions else None
|
| 627 |
+
|
| 628 |
+
for i, layer_module in enumerate(self.layer):
|
| 629 |
+
if output_hidden_states:
|
| 630 |
+
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 631 |
+
|
| 632 |
+
if self.has_relative_position_bias:
|
| 633 |
+
height, width = resolution
|
| 634 |
+
window_size = (height // self.config.patch_size, width // self.config.patch_size)
|
| 635 |
+
relative_position_bias = self.relative_position_bias(
|
| 636 |
+
window_size, interpolate_pos_encoding=interpolate_pos_encoding, dim_size=hidden_states.shape[1]
|
| 637 |
+
)
|
| 638 |
+
else:
|
| 639 |
+
relative_position_bias = None
|
| 640 |
+
|
| 641 |
+
layer_outputs = layer_module(
|
| 642 |
+
hidden_states,
|
| 643 |
+
output_attentions=output_attentions,
|
| 644 |
+
relative_position_bias=relative_position_bias,
|
| 645 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 646 |
+
resolution=resolution,
|
| 647 |
+
)
|
| 648 |
+
|
| 649 |
+
hidden_states = layer_outputs[0]
|
| 650 |
+
|
| 651 |
+
if output_attentions:
|
| 652 |
+
all_self_attentions = all_self_attentions + (layer_outputs[1],)
|
| 653 |
+
|
| 654 |
+
if output_hidden_states:
|
| 655 |
+
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 656 |
+
|
| 657 |
+
if not return_dict:
|
| 658 |
+
return tuple(v for v in [hidden_states, all_hidden_states, all_self_attentions] if v is not None)
|
| 659 |
+
return BaseModelOutput(
|
| 660 |
+
last_hidden_state=hidden_states,
|
| 661 |
+
hidden_states=all_hidden_states,
|
| 662 |
+
attentions=all_self_attentions,
|
| 663 |
+
)
|
| 664 |
+
|
| 665 |
+
|
| 666 |
+
@auto_docstring
|
| 667 |
+
class BeitPreTrainedModel(PreTrainedModel):
|
| 668 |
+
config: BeitConfig
|
| 669 |
+
base_model_prefix = "beit"
|
| 670 |
+
input_modalities = ("image",)
|
| 671 |
+
main_input_name = "pixel_values"
|
| 672 |
+
supports_gradient_checkpointing = True
|
| 673 |
+
_no_split_modules = ["BeitLayer"]
|
| 674 |
+
_keys_to_ignore_on_load_unexpected = [r".*relative_position_index.*"]
|
| 675 |
+
_supports_sdpa = True
|
| 676 |
+
|
| 677 |
+
@torch.no_grad()
|
| 678 |
+
def _init_weights(self, module):
|
| 679 |
+
"""Initialize the weights"""
|
| 680 |
+
super()._init_weights(module)
|
| 681 |
+
if isinstance(module, BeitEmbeddings):
|
| 682 |
+
init.zeros_(module.cls_token)
|
| 683 |
+
if module.mask_token is not None:
|
| 684 |
+
init.zeros_(module.mask_token)
|
| 685 |
+
if module.position_embeddings is not None:
|
| 686 |
+
init.zeros_(module.position_embeddings)
|
| 687 |
+
elif isinstance(module, BeitRelativePositionBias):
|
| 688 |
+
init.zeros_(module.relative_position_bias_table)
|
| 689 |
+
elif isinstance(module, BeitLayer):
|
| 690 |
+
if module.lambda_1 is not None:
|
| 691 |
+
init.constant_(module.lambda_1, self.config.layer_scale_init_value)
|
| 692 |
+
init.constant_(module.lambda_2, self.config.layer_scale_init_value)
|
| 693 |
+
|
| 694 |
+
|
| 695 |
+
@auto_docstring
|
| 696 |
+
class BeitModel(BeitPreTrainedModel):
|
| 697 |
+
def __init__(self, config: BeitConfig, add_pooling_layer: bool = True) -> None:
|
| 698 |
+
r"""
|
| 699 |
+
add_pooling_layer (bool, *optional*, defaults to `True`):
|
| 700 |
+
Whether to add a pooling layer
|
| 701 |
+
"""
|
| 702 |
+
super().__init__(config)
|
| 703 |
+
self.config = config
|
| 704 |
+
|
| 705 |
+
self.embeddings = BeitEmbeddings(config)
|
| 706 |
+
self.encoder = BeitEncoder(config, window_size=self.embeddings.patch_embeddings.patch_shape)
|
| 707 |
+
|
| 708 |
+
self.layernorm = (
|
| 709 |
+
nn.Identity() if config.use_mean_pooling else nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 710 |
+
)
|
| 711 |
+
self.pooler = BeitPooler(config) if add_pooling_layer else None
|
| 712 |
+
|
| 713 |
+
# Initialize weights and apply final processing
|
| 714 |
+
self.post_init()
|
| 715 |
+
|
| 716 |
+
def get_input_embeddings(self):
|
| 717 |
+
return self.embeddings.patch_embeddings
|
| 718 |
+
|
| 719 |
+
@auto_docstring
|
| 720 |
+
def forward(
|
| 721 |
+
self,
|
| 722 |
+
pixel_values: torch.Tensor,
|
| 723 |
+
bool_masked_pos: torch.BoolTensor | None = None,
|
| 724 |
+
output_attentions: bool | None = None,
|
| 725 |
+
output_hidden_states: bool | None = None,
|
| 726 |
+
interpolate_pos_encoding: bool = False,
|
| 727 |
+
return_dict: bool | None = None,
|
| 728 |
+
**kwargs,
|
| 729 |
+
) -> tuple | BeitModelOutputWithPooling:
|
| 730 |
+
r"""
|
| 731 |
+
bool_masked_pos (`torch.BoolTensor` of shape `(batch_size, num_patches)`, *optional*):
|
| 732 |
+
Boolean masked positions. Indicates which patches are masked (1) and which aren't (0).
|
| 733 |
+
"""
|
| 734 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 735 |
+
output_hidden_states = (
|
| 736 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 737 |
+
)
|
| 738 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 739 |
+
|
| 740 |
+
embedding_output, _ = self.embeddings(pixel_values, bool_masked_pos=bool_masked_pos)
|
| 741 |
+
resolution = pixel_values.shape[2:]
|
| 742 |
+
|
| 743 |
+
encoder_outputs = self.encoder(
|
| 744 |
+
embedding_output,
|
| 745 |
+
output_attentions=output_attentions,
|
| 746 |
+
output_hidden_states=output_hidden_states,
|
| 747 |
+
resolution=resolution,
|
| 748 |
+
return_dict=return_dict,
|
| 749 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 750 |
+
)
|
| 751 |
+
sequence_output = encoder_outputs[0]
|
| 752 |
+
sequence_output = self.layernorm(sequence_output)
|
| 753 |
+
pooled_output = self.pooler(sequence_output) if self.pooler is not None else None
|
| 754 |
+
|
| 755 |
+
if not return_dict:
|
| 756 |
+
head_outputs = (sequence_output, pooled_output) if pooled_output is not None else (sequence_output,)
|
| 757 |
+
return head_outputs + encoder_outputs[1:]
|
| 758 |
+
|
| 759 |
+
return BeitModelOutputWithPooling(
|
| 760 |
+
last_hidden_state=sequence_output,
|
| 761 |
+
pooler_output=pooled_output,
|
| 762 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 763 |
+
attentions=encoder_outputs.attentions,
|
| 764 |
+
)
|
| 765 |
+
|
| 766 |
+
|
| 767 |
+
class BeitPooler(nn.Module):
|
| 768 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 769 |
+
super().__init__()
|
| 770 |
+
self.layernorm = (
|
| 771 |
+
nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps) if config.use_mean_pooling else None
|
| 772 |
+
)
|
| 773 |
+
|
| 774 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 775 |
+
if self.layernorm is not None:
|
| 776 |
+
# Mean pool the final hidden states of the patch tokens
|
| 777 |
+
patch_tokens = hidden_states[:, 1:, :]
|
| 778 |
+
pooled_output = self.layernorm(patch_tokens.mean(1))
|
| 779 |
+
else:
|
| 780 |
+
# Pool by simply taking the final hidden state of the [CLS] token
|
| 781 |
+
pooled_output = hidden_states[:, 0]
|
| 782 |
+
|
| 783 |
+
return pooled_output
|
| 784 |
+
|
| 785 |
+
|
| 786 |
+
@auto_docstring(
|
| 787 |
+
custom_intro="""
|
| 788 |
+
Beit Model transformer with a 'language' modeling head on top. BEiT does masked image modeling by predicting
|
| 789 |
+
visual tokens of a Vector-Quantize Variational Autoencoder (VQ-VAE), whereas other vision models like ViT and DeiT
|
| 790 |
+
predict RGB pixel values. As a result, this class is incompatible with [`AutoModelForMaskedImageModeling`], so you
|
| 791 |
+
will need to use [`BeitForMaskedImageModeling`] directly if you wish to do masked image modeling with BEiT.
|
| 792 |
+
"""
|
| 793 |
+
)
|
| 794 |
+
class BeitForMaskedImageModeling(BeitPreTrainedModel):
|
| 795 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 796 |
+
super().__init__(config)
|
| 797 |
+
|
| 798 |
+
self.num_labels = config.num_labels
|
| 799 |
+
self.beit = BeitModel(config, add_pooling_layer=False)
|
| 800 |
+
|
| 801 |
+
# Classifier head
|
| 802 |
+
self.layernorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 803 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size)
|
| 804 |
+
|
| 805 |
+
# Initialize weights and apply final processing
|
| 806 |
+
self.post_init()
|
| 807 |
+
|
| 808 |
+
def get_output_embeddings(self):
|
| 809 |
+
return None
|
| 810 |
+
|
| 811 |
+
@auto_docstring
|
| 812 |
+
def forward(
|
| 813 |
+
self,
|
| 814 |
+
pixel_values: torch.Tensor | None = None,
|
| 815 |
+
bool_masked_pos: torch.BoolTensor | None = None,
|
| 816 |
+
labels: torch.Tensor | None = None,
|
| 817 |
+
output_attentions: bool | None = None,
|
| 818 |
+
output_hidden_states: bool | None = None,
|
| 819 |
+
interpolate_pos_encoding: bool = False,
|
| 820 |
+
return_dict: bool | None = None,
|
| 821 |
+
**kwargs,
|
| 822 |
+
) -> tuple | MaskedLMOutput:
|
| 823 |
+
r"""
|
| 824 |
+
bool_masked_pos (`torch.BoolTensor` of shape `(batch_size, num_patches)`):
|
| 825 |
+
Boolean masked positions. Indicates which patches are masked (1) and which aren't (0).
|
| 826 |
+
labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
|
| 827 |
+
Labels for computing the image classification/regression loss. Indices should be in `[0, ...,
|
| 828 |
+
config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
|
| 829 |
+
`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
| 830 |
+
|
| 831 |
+
Examples:
|
| 832 |
+
|
| 833 |
+
```python
|
| 834 |
+
>>> from transformers import AutoImageProcessor, BeitForMaskedImageModeling
|
| 835 |
+
>>> import torch
|
| 836 |
+
>>> from PIL import Image
|
| 837 |
+
>>> import httpx
|
| 838 |
+
>>> from io import BytesIO
|
| 839 |
+
|
| 840 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 841 |
+
>>> with httpx.stream("GET", url) as response:
|
| 842 |
+
... image = Image.open(BytesIO(response.read()))
|
| 843 |
+
|
| 844 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("microsoft/beit-base-patch16-224-pt22k")
|
| 845 |
+
>>> model = BeitForMaskedImageModeling.from_pretrained("microsoft/beit-base-patch16-224-pt22k")
|
| 846 |
+
|
| 847 |
+
>>> num_patches = (model.config.image_size // model.config.patch_size) ** 2
|
| 848 |
+
>>> pixel_values = image_processor(images=image, return_tensors="pt").pixel_values
|
| 849 |
+
>>> # create random boolean mask of shape (batch_size, num_patches)
|
| 850 |
+
>>> bool_masked_pos = torch.randint(low=0, high=2, size=(1, num_patches)).bool()
|
| 851 |
+
|
| 852 |
+
>>> outputs = model(pixel_values, bool_masked_pos=bool_masked_pos)
|
| 853 |
+
>>> loss, logits = outputs.loss, outputs.logits
|
| 854 |
+
>>> list(logits.shape)
|
| 855 |
+
[1, 196, 8192]
|
| 856 |
+
```"""
|
| 857 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 858 |
+
|
| 859 |
+
outputs = self.beit(
|
| 860 |
+
pixel_values,
|
| 861 |
+
bool_masked_pos=bool_masked_pos,
|
| 862 |
+
output_attentions=output_attentions,
|
| 863 |
+
output_hidden_states=output_hidden_states,
|
| 864 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 865 |
+
return_dict=return_dict,
|
| 866 |
+
)
|
| 867 |
+
|
| 868 |
+
sequence_output = outputs[0]
|
| 869 |
+
sequence_output = self.layernorm(sequence_output)
|
| 870 |
+
prediction_scores = self.lm_head(sequence_output[:, 1:])
|
| 871 |
+
|
| 872 |
+
masked_lm_loss = None
|
| 873 |
+
if labels is not None:
|
| 874 |
+
loss_fct = CrossEntropyLoss() # -100 index = padding token
|
| 875 |
+
masked_lm_loss = loss_fct(prediction_scores[bool_masked_pos], labels)
|
| 876 |
+
|
| 877 |
+
if not return_dict:
|
| 878 |
+
output = (prediction_scores,) + outputs[1:]
|
| 879 |
+
return ((masked_lm_loss,) + output) if masked_lm_loss is not None else output
|
| 880 |
+
|
| 881 |
+
return MaskedLMOutput(
|
| 882 |
+
loss=masked_lm_loss,
|
| 883 |
+
logits=prediction_scores,
|
| 884 |
+
hidden_states=outputs.hidden_states,
|
| 885 |
+
attentions=outputs.attentions,
|
| 886 |
+
)
|
| 887 |
+
|
| 888 |
+
|
| 889 |
+
@auto_docstring(
|
| 890 |
+
custom_intro="""
|
| 891 |
+
Beit Model transformer with an image classification head on top (a linear layer on top of the average of the final
|
| 892 |
+
hidden states of the patch tokens) e.g. for ImageNet.
|
| 893 |
+
"""
|
| 894 |
+
)
|
| 895 |
+
class BeitForImageClassification(BeitPreTrainedModel):
|
| 896 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 897 |
+
super().__init__(config)
|
| 898 |
+
|
| 899 |
+
self.num_labels = config.num_labels
|
| 900 |
+
self.beit = BeitModel(config, add_pooling_layer=True)
|
| 901 |
+
|
| 902 |
+
# Classifier head
|
| 903 |
+
self.classifier = nn.Linear(config.hidden_size, config.num_labels) if config.num_labels > 0 else nn.Identity()
|
| 904 |
+
|
| 905 |
+
# Initialize weights and apply final processing
|
| 906 |
+
self.post_init()
|
| 907 |
+
|
| 908 |
+
@auto_docstring
|
| 909 |
+
def forward(
|
| 910 |
+
self,
|
| 911 |
+
pixel_values: torch.Tensor | None = None,
|
| 912 |
+
labels: torch.Tensor | None = None,
|
| 913 |
+
output_attentions: bool | None = None,
|
| 914 |
+
output_hidden_states: bool | None = None,
|
| 915 |
+
interpolate_pos_encoding: bool = False,
|
| 916 |
+
return_dict: bool | None = None,
|
| 917 |
+
**kwargs,
|
| 918 |
+
) -> tuple | ImageClassifierOutput:
|
| 919 |
+
r"""
|
| 920 |
+
labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
|
| 921 |
+
Labels for computing the image classification/regression loss. Indices should be in `[0, ...,
|
| 922 |
+
config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
|
| 923 |
+
`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
| 924 |
+
"""
|
| 925 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 926 |
+
outputs = self.beit(
|
| 927 |
+
pixel_values,
|
| 928 |
+
output_attentions=output_attentions,
|
| 929 |
+
output_hidden_states=output_hidden_states,
|
| 930 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 931 |
+
return_dict=return_dict,
|
| 932 |
+
)
|
| 933 |
+
|
| 934 |
+
pooled_output = outputs.pooler_output if return_dict else outputs[1]
|
| 935 |
+
|
| 936 |
+
logits = self.classifier(pooled_output)
|
| 937 |
+
|
| 938 |
+
loss = None
|
| 939 |
+
if labels is not None:
|
| 940 |
+
loss = self.loss_function(labels, logits, self.config)
|
| 941 |
+
|
| 942 |
+
if not return_dict:
|
| 943 |
+
output = (logits,) + outputs[2:]
|
| 944 |
+
return ((loss,) + output) if loss is not None else output
|
| 945 |
+
|
| 946 |
+
return ImageClassifierOutput(
|
| 947 |
+
loss=loss,
|
| 948 |
+
logits=logits,
|
| 949 |
+
hidden_states=outputs.hidden_states,
|
| 950 |
+
attentions=outputs.attentions,
|
| 951 |
+
)
|
| 952 |
+
|
| 953 |
+
|
| 954 |
+
class BeitConvModule(nn.Module):
|
| 955 |
+
"""
|
| 956 |
+
A convolutional block that bundles conv/norm/activation layers. This block simplifies the usage of convolution
|
| 957 |
+
layers, which are commonly used with a norm layer (e.g., BatchNorm) and activation layer (e.g., ReLU).
|
| 958 |
+
|
| 959 |
+
Based on OpenMMLab's implementation, found in https://github.com/open-mmlab/mmsegmentation.
|
| 960 |
+
"""
|
| 961 |
+
|
| 962 |
+
def __init__(
|
| 963 |
+
self,
|
| 964 |
+
in_channels: int,
|
| 965 |
+
out_channels: int,
|
| 966 |
+
kernel_size: int | tuple[int, int],
|
| 967 |
+
padding: int | tuple[int, int] | str = 0,
|
| 968 |
+
bias: bool = False,
|
| 969 |
+
dilation: int | tuple[int, int] = 1,
|
| 970 |
+
) -> None:
|
| 971 |
+
super().__init__()
|
| 972 |
+
self.conv = nn.Conv2d(
|
| 973 |
+
in_channels=in_channels,
|
| 974 |
+
out_channels=out_channels,
|
| 975 |
+
kernel_size=kernel_size,
|
| 976 |
+
padding=padding,
|
| 977 |
+
bias=bias,
|
| 978 |
+
dilation=dilation,
|
| 979 |
+
)
|
| 980 |
+
self.bn = nn.BatchNorm2d(out_channels)
|
| 981 |
+
self.activation = nn.ReLU()
|
| 982 |
+
|
| 983 |
+
def forward(self, input: torch.Tensor) -> torch.Tensor:
|
| 984 |
+
output = self.conv(input)
|
| 985 |
+
output = self.bn(output)
|
| 986 |
+
output = self.activation(output)
|
| 987 |
+
|
| 988 |
+
return output
|
| 989 |
+
|
| 990 |
+
|
| 991 |
+
class BeitPyramidPoolingBlock(nn.Module):
|
| 992 |
+
def __init__(self, pool_scale: int, in_channels: int, channels: int) -> None:
|
| 993 |
+
super().__init__()
|
| 994 |
+
self.layers = [
|
| 995 |
+
nn.AdaptiveAvgPool2d(pool_scale),
|
| 996 |
+
BeitConvModule(in_channels, channels, kernel_size=1),
|
| 997 |
+
]
|
| 998 |
+
for i, layer in enumerate(self.layers):
|
| 999 |
+
self.add_module(str(i), layer)
|
| 1000 |
+
|
| 1001 |
+
def forward(self, input: torch.Tensor) -> torch.Tensor:
|
| 1002 |
+
hidden_state = input
|
| 1003 |
+
for layer in self.layers:
|
| 1004 |
+
hidden_state = layer(hidden_state)
|
| 1005 |
+
return hidden_state
|
| 1006 |
+
|
| 1007 |
+
|
| 1008 |
+
class BeitPyramidPoolingModule(nn.Module):
|
| 1009 |
+
"""
|
| 1010 |
+
Pyramid Pooling Module (PPM) used in PSPNet.
|
| 1011 |
+
|
| 1012 |
+
Args:
|
| 1013 |
+
pool_scales (tuple[int]): Pooling scales used in Pooling Pyramid
|
| 1014 |
+
Module.
|
| 1015 |
+
in_channels (int): Input channels.
|
| 1016 |
+
channels (int): Channels after modules, before conv_seg.
|
| 1017 |
+
align_corners (bool): align_corners argument of F.interpolate.
|
| 1018 |
+
|
| 1019 |
+
Based on OpenMMLab's implementation, found in https://github.com/open-mmlab/mmsegmentation.
|
| 1020 |
+
"""
|
| 1021 |
+
|
| 1022 |
+
def __init__(self, pool_scales: tuple[int, ...], in_channels: int, channels: int, align_corners: bool) -> None:
|
| 1023 |
+
super().__init__()
|
| 1024 |
+
self.pool_scales = pool_scales
|
| 1025 |
+
self.align_corners = align_corners
|
| 1026 |
+
self.in_channels = in_channels
|
| 1027 |
+
self.channels = channels
|
| 1028 |
+
self.blocks = []
|
| 1029 |
+
for i, pool_scale in enumerate(pool_scales):
|
| 1030 |
+
block = BeitPyramidPoolingBlock(pool_scale=pool_scale, in_channels=in_channels, channels=channels)
|
| 1031 |
+
self.blocks.append(block)
|
| 1032 |
+
self.add_module(str(i), block)
|
| 1033 |
+
|
| 1034 |
+
def forward(self, x: torch.Tensor) -> list[torch.Tensor]:
|
| 1035 |
+
ppm_outs = []
|
| 1036 |
+
for ppm in self.blocks:
|
| 1037 |
+
ppm_out = ppm(x)
|
| 1038 |
+
upsampled_ppm_out = nn.functional.interpolate(
|
| 1039 |
+
ppm_out, size=x.size()[2:], mode="bilinear", align_corners=self.align_corners
|
| 1040 |
+
)
|
| 1041 |
+
ppm_outs.append(upsampled_ppm_out)
|
| 1042 |
+
return ppm_outs
|
| 1043 |
+
|
| 1044 |
+
|
| 1045 |
+
class BeitUperHead(nn.Module):
|
| 1046 |
+
"""
|
| 1047 |
+
Unified Perceptual Parsing for Scene Understanding. This head is the implementation of
|
| 1048 |
+
[UPerNet](https://huggingface.co/papers/1807.10221).
|
| 1049 |
+
|
| 1050 |
+
Based on OpenMMLab's implementation, found in https://github.com/open-mmlab/mmsegmentation.
|
| 1051 |
+
"""
|
| 1052 |
+
|
| 1053 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 1054 |
+
super().__init__()
|
| 1055 |
+
|
| 1056 |
+
self.pool_scales = config.pool_scales # e.g. (1, 2, 3, 6)
|
| 1057 |
+
self.in_channels = [config.hidden_size] * 4 # e.g. [768, 768, 768, 768]
|
| 1058 |
+
self.channels = config.hidden_size
|
| 1059 |
+
self.align_corners = False
|
| 1060 |
+
self.classifier = nn.Conv2d(self.channels, config.num_labels, kernel_size=1)
|
| 1061 |
+
|
| 1062 |
+
# PSP Module
|
| 1063 |
+
self.psp_modules = BeitPyramidPoolingModule(
|
| 1064 |
+
self.pool_scales,
|
| 1065 |
+
self.in_channels[-1],
|
| 1066 |
+
self.channels,
|
| 1067 |
+
align_corners=self.align_corners,
|
| 1068 |
+
)
|
| 1069 |
+
self.bottleneck = BeitConvModule(
|
| 1070 |
+
self.in_channels[-1] + len(self.pool_scales) * self.channels,
|
| 1071 |
+
self.channels,
|
| 1072 |
+
kernel_size=3,
|
| 1073 |
+
padding=1,
|
| 1074 |
+
)
|
| 1075 |
+
# FPN Module
|
| 1076 |
+
self.lateral_convs = nn.ModuleList()
|
| 1077 |
+
self.fpn_convs = nn.ModuleList()
|
| 1078 |
+
for in_channels in self.in_channels[:-1]: # skip the top layer
|
| 1079 |
+
l_conv = BeitConvModule(in_channels, self.channels, kernel_size=1)
|
| 1080 |
+
fpn_conv = BeitConvModule(self.channels, self.channels, kernel_size=3, padding=1)
|
| 1081 |
+
self.lateral_convs.append(l_conv)
|
| 1082 |
+
self.fpn_convs.append(fpn_conv)
|
| 1083 |
+
|
| 1084 |
+
self.fpn_bottleneck = BeitConvModule(
|
| 1085 |
+
len(self.in_channels) * self.channels,
|
| 1086 |
+
self.channels,
|
| 1087 |
+
kernel_size=3,
|
| 1088 |
+
padding=1,
|
| 1089 |
+
)
|
| 1090 |
+
|
| 1091 |
+
def psp_forward(self, inputs):
|
| 1092 |
+
x = inputs[-1]
|
| 1093 |
+
psp_outs = [x]
|
| 1094 |
+
psp_outs.extend(self.psp_modules(x))
|
| 1095 |
+
psp_outs = torch.cat(psp_outs, dim=1)
|
| 1096 |
+
output = self.bottleneck(psp_outs)
|
| 1097 |
+
|
| 1098 |
+
return output
|
| 1099 |
+
|
| 1100 |
+
def forward(self, encoder_hidden_states: torch.Tensor) -> torch.Tensor:
|
| 1101 |
+
# build laterals
|
| 1102 |
+
laterals = [lateral_conv(encoder_hidden_states[i]) for i, lateral_conv in enumerate(self.lateral_convs)]
|
| 1103 |
+
|
| 1104 |
+
laterals.append(self.psp_forward(encoder_hidden_states))
|
| 1105 |
+
|
| 1106 |
+
# build top-down path
|
| 1107 |
+
used_backbone_levels = len(laterals)
|
| 1108 |
+
for i in range(used_backbone_levels - 1, 0, -1):
|
| 1109 |
+
prev_shape = laterals[i - 1].shape[2:]
|
| 1110 |
+
laterals[i - 1] = laterals[i - 1] + nn.functional.interpolate(
|
| 1111 |
+
laterals[i], size=prev_shape, mode="bilinear", align_corners=self.align_corners
|
| 1112 |
+
)
|
| 1113 |
+
|
| 1114 |
+
# build outputs
|
| 1115 |
+
fpn_outs = [self.fpn_convs[i](laterals[i]) for i in range(used_backbone_levels - 1)]
|
| 1116 |
+
# append psp feature
|
| 1117 |
+
fpn_outs.append(laterals[-1])
|
| 1118 |
+
|
| 1119 |
+
for i in range(used_backbone_levels - 1, 0, -1):
|
| 1120 |
+
fpn_outs[i] = nn.functional.interpolate(
|
| 1121 |
+
fpn_outs[i], size=fpn_outs[0].shape[2:], mode="bilinear", align_corners=self.align_corners
|
| 1122 |
+
)
|
| 1123 |
+
fpn_outs = torch.cat(fpn_outs, dim=1)
|
| 1124 |
+
output = self.fpn_bottleneck(fpn_outs)
|
| 1125 |
+
output = self.classifier(output)
|
| 1126 |
+
|
| 1127 |
+
return output
|
| 1128 |
+
|
| 1129 |
+
|
| 1130 |
+
class BeitFCNHead(nn.Module):
|
| 1131 |
+
"""
|
| 1132 |
+
Fully Convolution Networks for Semantic Segmentation. This head is implemented of
|
| 1133 |
+
[FCNNet](https://huggingface.co/papers/1411.4038>).
|
| 1134 |
+
|
| 1135 |
+
Args:
|
| 1136 |
+
config (BeitConfig): Configuration.
|
| 1137 |
+
in_channels
|
| 1138 |
+
kernel_size (int): The kernel size for convs in the head. Default: 3.
|
| 1139 |
+
dilation (int): The dilation rate for convs in the head. Default: 1.
|
| 1140 |
+
|
| 1141 |
+
|
| 1142 |
+
Based on OpenMMLab's implementation, found in https://github.com/open-mmlab/mmsegmentation.
|
| 1143 |
+
"""
|
| 1144 |
+
|
| 1145 |
+
def __init__(
|
| 1146 |
+
self, config: BeitConfig, in_index: int = 2, kernel_size: int = 3, dilation: int | tuple[int, int] = 1
|
| 1147 |
+
) -> None:
|
| 1148 |
+
super().__init__()
|
| 1149 |
+
self.in_channels = config.hidden_size
|
| 1150 |
+
self.channels = config.auxiliary_channels
|
| 1151 |
+
self.num_convs = config.auxiliary_num_convs
|
| 1152 |
+
self.concat_input = config.auxiliary_concat_input
|
| 1153 |
+
self.in_index = in_index
|
| 1154 |
+
|
| 1155 |
+
conv_padding = (kernel_size // 2) * dilation
|
| 1156 |
+
convs = []
|
| 1157 |
+
convs.append(
|
| 1158 |
+
BeitConvModule(
|
| 1159 |
+
self.in_channels, self.channels, kernel_size=kernel_size, padding=conv_padding, dilation=dilation
|
| 1160 |
+
)
|
| 1161 |
+
)
|
| 1162 |
+
for i in range(self.num_convs - 1):
|
| 1163 |
+
convs.append(
|
| 1164 |
+
BeitConvModule(
|
| 1165 |
+
self.channels, self.channels, kernel_size=kernel_size, padding=conv_padding, dilation=dilation
|
| 1166 |
+
)
|
| 1167 |
+
)
|
| 1168 |
+
if self.num_convs == 0:
|
| 1169 |
+
self.convs = nn.Identity()
|
| 1170 |
+
else:
|
| 1171 |
+
self.convs = nn.Sequential(*convs)
|
| 1172 |
+
if self.concat_input:
|
| 1173 |
+
self.conv_cat = BeitConvModule(
|
| 1174 |
+
self.in_channels + self.channels, self.channels, kernel_size=kernel_size, padding=kernel_size // 2
|
| 1175 |
+
)
|
| 1176 |
+
|
| 1177 |
+
self.classifier = nn.Conv2d(self.channels, config.num_labels, kernel_size=1)
|
| 1178 |
+
|
| 1179 |
+
def forward(self, encoder_hidden_states: torch.Tensor) -> torch.Tensor:
|
| 1180 |
+
# just take the relevant feature maps
|
| 1181 |
+
hidden_states = encoder_hidden_states[self.in_index]
|
| 1182 |
+
output = self.convs(hidden_states)
|
| 1183 |
+
if self.concat_input:
|
| 1184 |
+
output = self.conv_cat(torch.cat([hidden_states, output], dim=1))
|
| 1185 |
+
output = self.classifier(output)
|
| 1186 |
+
return output
|
| 1187 |
+
|
| 1188 |
+
|
| 1189 |
+
@auto_docstring
|
| 1190 |
+
class BeitForSemanticSegmentation(BeitPreTrainedModel):
|
| 1191 |
+
def __init__(self, config: BeitConfig) -> None:
|
| 1192 |
+
super().__init__(config)
|
| 1193 |
+
|
| 1194 |
+
self.num_labels = config.num_labels
|
| 1195 |
+
self.beit = BeitModel(config, add_pooling_layer=False)
|
| 1196 |
+
|
| 1197 |
+
# FPNs
|
| 1198 |
+
if len(self.config.out_indices) != 4:
|
| 1199 |
+
raise ValueError(
|
| 1200 |
+
"BeitForSemanticSegmentation requires config.out_indices to be a list of 4 integers, "
|
| 1201 |
+
"specifying which features to use from the backbone. One can use [3, 5, 7, 11] in case of "
|
| 1202 |
+
"a base-sized architecture."
|
| 1203 |
+
)
|
| 1204 |
+
self.fpn1 = nn.Sequential(
|
| 1205 |
+
nn.ConvTranspose2d(config.hidden_size, config.hidden_size, kernel_size=2, stride=2),
|
| 1206 |
+
nn.BatchNorm2d(config.hidden_size),
|
| 1207 |
+
nn.GELU(),
|
| 1208 |
+
nn.ConvTranspose2d(config.hidden_size, config.hidden_size, kernel_size=2, stride=2),
|
| 1209 |
+
)
|
| 1210 |
+
self.fpn2 = nn.Sequential(
|
| 1211 |
+
nn.ConvTranspose2d(config.hidden_size, config.hidden_size, kernel_size=2, stride=2),
|
| 1212 |
+
)
|
| 1213 |
+
self.fpn3 = nn.Identity()
|
| 1214 |
+
self.fpn4 = nn.MaxPool2d(kernel_size=2, stride=2)
|
| 1215 |
+
|
| 1216 |
+
# Semantic segmentation head(s)
|
| 1217 |
+
self.decode_head = BeitUperHead(config)
|
| 1218 |
+
self.auxiliary_head = BeitFCNHead(config) if config.use_auxiliary_head else None
|
| 1219 |
+
|
| 1220 |
+
# Initialize weights and apply final processing
|
| 1221 |
+
self.post_init()
|
| 1222 |
+
|
| 1223 |
+
def compute_loss(self, logits, auxiliary_logits, labels):
|
| 1224 |
+
# upsample logits to the images' original size
|
| 1225 |
+
upsampled_logits = nn.functional.interpolate(
|
| 1226 |
+
logits, size=labels.shape[-2:], mode="bilinear", align_corners=False
|
| 1227 |
+
)
|
| 1228 |
+
if auxiliary_logits is not None:
|
| 1229 |
+
upsampled_auxiliary_logits = nn.functional.interpolate(
|
| 1230 |
+
auxiliary_logits, size=labels.shape[-2:], mode="bilinear", align_corners=False
|
| 1231 |
+
)
|
| 1232 |
+
# compute weighted loss
|
| 1233 |
+
loss_fct = CrossEntropyLoss(ignore_index=self.config.semantic_loss_ignore_index)
|
| 1234 |
+
main_loss = loss_fct(upsampled_logits, labels)
|
| 1235 |
+
loss = main_loss
|
| 1236 |
+
if auxiliary_logits is not None:
|
| 1237 |
+
auxiliary_loss = loss_fct(upsampled_auxiliary_logits, labels)
|
| 1238 |
+
loss += self.config.auxiliary_loss_weight * auxiliary_loss
|
| 1239 |
+
|
| 1240 |
+
return loss
|
| 1241 |
+
|
| 1242 |
+
@auto_docstring
|
| 1243 |
+
def forward(
|
| 1244 |
+
self,
|
| 1245 |
+
pixel_values: torch.Tensor | None = None,
|
| 1246 |
+
labels: torch.Tensor | None = None,
|
| 1247 |
+
output_attentions: bool | None = None,
|
| 1248 |
+
output_hidden_states: bool | None = None,
|
| 1249 |
+
interpolate_pos_encoding: bool = False,
|
| 1250 |
+
return_dict: bool | None = None,
|
| 1251 |
+
**kwargs,
|
| 1252 |
+
) -> tuple | SemanticSegmenterOutput:
|
| 1253 |
+
r"""
|
| 1254 |
+
labels (`torch.LongTensor` of shape `(batch_size, height, width)`, *optional*):
|
| 1255 |
+
Ground truth semantic segmentation maps for computing the loss. Indices should be in `[0, ...,
|
| 1256 |
+
config.num_labels - 1]`. If `config.num_labels > 1`, a classification loss is computed (Cross-Entropy).
|
| 1257 |
+
|
| 1258 |
+
Examples:
|
| 1259 |
+
|
| 1260 |
+
```python
|
| 1261 |
+
>>> from transformers import AutoImageProcessor, BeitForSemanticSegmentation
|
| 1262 |
+
>>> from PIL import Image
|
| 1263 |
+
>>> import httpx
|
| 1264 |
+
>>> from io import BytesIO
|
| 1265 |
+
|
| 1266 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1267 |
+
>>> with httpx.stream("GET", url) as response:
|
| 1268 |
+
... image = Image.open(BytesIO(response.read()))
|
| 1269 |
+
|
| 1270 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("microsoft/beit-base-finetuned-ade-640-640")
|
| 1271 |
+
>>> model = BeitForSemanticSegmentation.from_pretrained("microsoft/beit-base-finetuned-ade-640-640")
|
| 1272 |
+
|
| 1273 |
+
>>> inputs = image_processor(images=image, return_tensors="pt")
|
| 1274 |
+
>>> outputs = model(**inputs)
|
| 1275 |
+
>>> # logits are of shape (batch_size, num_labels, height, width)
|
| 1276 |
+
>>> logits = outputs.logits
|
| 1277 |
+
```"""
|
| 1278 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1279 |
+
output_hidden_states = (
|
| 1280 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 1281 |
+
)
|
| 1282 |
+
|
| 1283 |
+
if labels is not None and self.config.num_labels == 1:
|
| 1284 |
+
raise ValueError("The number of labels should be greater than one")
|
| 1285 |
+
|
| 1286 |
+
outputs = self.beit(
|
| 1287 |
+
pixel_values,
|
| 1288 |
+
output_attentions=output_attentions,
|
| 1289 |
+
output_hidden_states=True, # we need the intermediate hidden states
|
| 1290 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 1291 |
+
return_dict=return_dict,
|
| 1292 |
+
)
|
| 1293 |
+
|
| 1294 |
+
encoder_hidden_states = outputs.hidden_states if return_dict else outputs[1]
|
| 1295 |
+
|
| 1296 |
+
# only keep certain features, and reshape
|
| 1297 |
+
# note that we do +1 as the encoder_hidden_states also includes the initial embeddings
|
| 1298 |
+
features = [feature for idx, feature in enumerate(encoder_hidden_states) if idx + 1 in self.config.out_indices]
|
| 1299 |
+
batch_size = pixel_values.shape[0]
|
| 1300 |
+
patch_resolution = self.config.image_size // self.config.patch_size
|
| 1301 |
+
features = [
|
| 1302 |
+
x[:, 1:, :].permute(0, 2, 1).reshape(batch_size, -1, patch_resolution, patch_resolution) for x in features
|
| 1303 |
+
]
|
| 1304 |
+
|
| 1305 |
+
# apply FPNs
|
| 1306 |
+
ops = [self.fpn1, self.fpn2, self.fpn3, self.fpn4]
|
| 1307 |
+
for i in range(len(features)):
|
| 1308 |
+
features[i] = ops[i](features[i])
|
| 1309 |
+
|
| 1310 |
+
logits = self.decode_head(features)
|
| 1311 |
+
|
| 1312 |
+
auxiliary_logits = None
|
| 1313 |
+
if self.auxiliary_head is not None:
|
| 1314 |
+
auxiliary_logits = self.auxiliary_head(features)
|
| 1315 |
+
|
| 1316 |
+
loss = None
|
| 1317 |
+
if labels is not None:
|
| 1318 |
+
loss = self.compute_loss(logits, auxiliary_logits, labels)
|
| 1319 |
+
|
| 1320 |
+
if not return_dict:
|
| 1321 |
+
if output_hidden_states:
|
| 1322 |
+
output = (logits,) + outputs[1:]
|
| 1323 |
+
else:
|
| 1324 |
+
output = (logits,) + outputs[2:]
|
| 1325 |
+
return ((loss,) + output) if loss is not None else output
|
| 1326 |
+
|
| 1327 |
+
return SemanticSegmenterOutput(
|
| 1328 |
+
loss=loss,
|
| 1329 |
+
logits=logits,
|
| 1330 |
+
hidden_states=outputs.hidden_states if output_hidden_states else None,
|
| 1331 |
+
attentions=outputs.attentions,
|
| 1332 |
+
)
|
| 1333 |
+
|
| 1334 |
+
|
| 1335 |
+
@auto_docstring(
|
| 1336 |
+
custom_intro="""
|
| 1337 |
+
BEiT backbone, to be used with frameworks like DETR and MaskFormer.
|
| 1338 |
+
"""
|
| 1339 |
+
)
|
| 1340 |
+
class BeitBackbone(BackboneMixin, BeitPreTrainedModel):
|
| 1341 |
+
def __init__(self, config):
|
| 1342 |
+
super().__init__(config)
|
| 1343 |
+
|
| 1344 |
+
self.num_features = [config.hidden_size for _ in range(config.num_hidden_layers + 1)]
|
| 1345 |
+
self.embeddings = BeitEmbeddings(config)
|
| 1346 |
+
self.encoder = BeitEncoder(config, window_size=self.embeddings.patch_embeddings.patch_shape)
|
| 1347 |
+
|
| 1348 |
+
if config.add_fpn:
|
| 1349 |
+
if len(self.config.out_indices) != 4:
|
| 1350 |
+
raise ValueError(
|
| 1351 |
+
"BeitBackbone requires config.out_indices to be a list of 4 integers, "
|
| 1352 |
+
"specifying which features to use from the backbone. One can use [3, 5, 7, 11] in case of "
|
| 1353 |
+
"a base-sized architecture."
|
| 1354 |
+
)
|
| 1355 |
+
hidden_size = config.hidden_size
|
| 1356 |
+
self.fpn1 = nn.Sequential(
|
| 1357 |
+
nn.ConvTranspose2d(hidden_size, hidden_size, kernel_size=2, stride=2),
|
| 1358 |
+
nn.BatchNorm2d(hidden_size, eps=config.batch_norm_eps),
|
| 1359 |
+
nn.GELU(),
|
| 1360 |
+
nn.ConvTranspose2d(hidden_size, hidden_size, kernel_size=2, stride=2),
|
| 1361 |
+
)
|
| 1362 |
+
|
| 1363 |
+
self.fpn2 = nn.Sequential(nn.ConvTranspose2d(hidden_size, hidden_size, kernel_size=2, stride=2))
|
| 1364 |
+
self.fpn3 = nn.Identity()
|
| 1365 |
+
self.fpn4 = nn.MaxPool2d(kernel_size=2, stride=2)
|
| 1366 |
+
|
| 1367 |
+
# initialize weights and apply final processing
|
| 1368 |
+
self.post_init()
|
| 1369 |
+
|
| 1370 |
+
def get_input_embeddings(self):
|
| 1371 |
+
return self.embeddings.patch_embeddings
|
| 1372 |
+
|
| 1373 |
+
@can_return_tuple
|
| 1374 |
+
@filter_output_hidden_states
|
| 1375 |
+
@auto_docstring
|
| 1376 |
+
def forward(
|
| 1377 |
+
self,
|
| 1378 |
+
pixel_values: Tensor,
|
| 1379 |
+
output_hidden_states: bool | None = None,
|
| 1380 |
+
output_attentions: bool | None = None,
|
| 1381 |
+
return_dict: bool | None = None,
|
| 1382 |
+
**kwargs,
|
| 1383 |
+
) -> BackboneOutput:
|
| 1384 |
+
r"""
|
| 1385 |
+
Examples:
|
| 1386 |
+
|
| 1387 |
+
```python
|
| 1388 |
+
>>> from transformers import AutoImageProcessor, AutoBackbone
|
| 1389 |
+
>>> import torch
|
| 1390 |
+
>>> from PIL import Image
|
| 1391 |
+
>>> import httpx
|
| 1392 |
+
>>> from io import BytesIO
|
| 1393 |
+
|
| 1394 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1395 |
+
>>> with httpx.stream("GET", url) as response:
|
| 1396 |
+
... image = Image.open(BytesIO(response.read()))
|
| 1397 |
+
|
| 1398 |
+
>>> processor = AutoImageProcessor.from_pretrained("microsoft/beit-base-patch16-224")
|
| 1399 |
+
>>> model = AutoBackbone.from_pretrained(
|
| 1400 |
+
... "microsoft/beit-base-patch16-224", out_features=["stage1", "stage2", "stage3", "stage4"]
|
| 1401 |
+
... )
|
| 1402 |
+
|
| 1403 |
+
>>> inputs = processor(image, return_tensors="pt")
|
| 1404 |
+
|
| 1405 |
+
>>> outputs = model(**inputs)
|
| 1406 |
+
>>> feature_maps = outputs.feature_maps
|
| 1407 |
+
>>> list(feature_maps[-1].shape)
|
| 1408 |
+
[1, 768, 14, 14]
|
| 1409 |
+
```"""
|
| 1410 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1411 |
+
output_hidden_states = (
|
| 1412 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 1413 |
+
)
|
| 1414 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 1415 |
+
|
| 1416 |
+
batch_size = pixel_values.shape[0]
|
| 1417 |
+
embedding_output, (patch_height, patch_width) = self.embeddings(pixel_values)
|
| 1418 |
+
resolution = pixel_values.shape[2:]
|
| 1419 |
+
|
| 1420 |
+
outputs = self.encoder(
|
| 1421 |
+
embedding_output,
|
| 1422 |
+
output_hidden_states=True,
|
| 1423 |
+
output_attentions=output_attentions,
|
| 1424 |
+
resolution=resolution,
|
| 1425 |
+
return_dict=return_dict,
|
| 1426 |
+
)
|
| 1427 |
+
|
| 1428 |
+
hidden_states = outputs.hidden_states if return_dict else outputs[1]
|
| 1429 |
+
|
| 1430 |
+
feature_maps = ()
|
| 1431 |
+
for stage, hidden_state in zip(self.stage_names, hidden_states):
|
| 1432 |
+
if stage in self.out_features:
|
| 1433 |
+
if self.config.reshape_hidden_states:
|
| 1434 |
+
hidden_state = hidden_state[:, 1:, :]
|
| 1435 |
+
hidden_state = hidden_state.permute(0, 2, 1)
|
| 1436 |
+
hidden_state = hidden_state.reshape(batch_size, -1, patch_height, patch_width)
|
| 1437 |
+
|
| 1438 |
+
feature_maps += (hidden_state,)
|
| 1439 |
+
|
| 1440 |
+
if self.config.add_fpn:
|
| 1441 |
+
feature_maps = [
|
| 1442 |
+
self.fpn1(feature_maps[0]),
|
| 1443 |
+
self.fpn2(feature_maps[1]),
|
| 1444 |
+
self.fpn3(feature_maps[2]),
|
| 1445 |
+
self.fpn4(feature_maps[3]),
|
| 1446 |
+
]
|
| 1447 |
+
feature_maps = tuple(feature_maps)
|
| 1448 |
+
|
| 1449 |
+
if not return_dict:
|
| 1450 |
+
if output_hidden_states:
|
| 1451 |
+
output = (feature_maps,) + outputs[1:]
|
| 1452 |
+
else:
|
| 1453 |
+
output = (feature_maps,) + outputs[2:]
|
| 1454 |
+
return output
|
| 1455 |
+
|
| 1456 |
+
return BackboneOutput(
|
| 1457 |
+
feature_maps=feature_maps,
|
| 1458 |
+
hidden_states=outputs.hidden_states if output_hidden_states else None,
|
| 1459 |
+
attentions=outputs.attentions,
|
| 1460 |
+
)
|
| 1461 |
+
|
| 1462 |
+
|
| 1463 |
+
__all__ = [
|
| 1464 |
+
"BeitForImageClassification",
|
| 1465 |
+
"BeitForMaskedImageModeling",
|
| 1466 |
+
"BeitForSemanticSegmentation",
|
| 1467 |
+
"BeitModel",
|
| 1468 |
+
"BeitPreTrainedModel",
|
| 1469 |
+
"BeitBackbone",
|
| 1470 |
+
]
|
third_party/transformers/src/transformers/models/cohere2/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 Cohere and The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_cohere2 import *
|
| 22 |
+
from .modeling_cohere2 import *
|
| 23 |
+
else:
|
| 24 |
+
import sys
|
| 25 |
+
|
| 26 |
+
_file = globals()["__file__"]
|
| 27 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/cohere2/configuration_cohere2.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/cohere2/modular_cohere2.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_cohere2.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2024 Cohere Inc. HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
#
|
| 10 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 11 |
+
# you may not use this file except in compliance with the License.
|
| 12 |
+
# You may obtain a copy of the License at
|
| 13 |
+
#
|
| 14 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 15 |
+
#
|
| 16 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 17 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 18 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 19 |
+
# See the License for the specific language governing permissions and
|
| 20 |
+
# limitations under the License.
|
| 21 |
+
from huggingface_hub.dataclasses import strict
|
| 22 |
+
|
| 23 |
+
from ...configuration_utils import PreTrainedConfig
|
| 24 |
+
from ...modeling_rope_utils import RopeParameters
|
| 25 |
+
from ...utils import auto_docstring
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@auto_docstring(checkpoint="CohereForAI/c4ai-command-r-v01")
|
| 29 |
+
@strict
|
| 30 |
+
class Cohere2Config(PreTrainedConfig):
|
| 31 |
+
r"""
|
| 32 |
+
logit_scale (`float`, *optional*, defaults to 0.0625):
|
| 33 |
+
The scaling factor for the output logits.
|
| 34 |
+
|
| 35 |
+
```python
|
| 36 |
+
>>> from transformers import Cohere2Model, Cohere2Config
|
| 37 |
+
|
| 38 |
+
>>> # Initializing a Cohere Nextmodel configuration
|
| 39 |
+
>>> configuration = Cohere2Config()
|
| 40 |
+
|
| 41 |
+
>>> # Initializing a model from the Cohere2 configuration
|
| 42 |
+
>>> model = Cohere2Model(configuration) # doctest: +SKIP
|
| 43 |
+
|
| 44 |
+
>>> # Accessing the model configuration
|
| 45 |
+
>>> configuration = model.config # doctest: +SKIP
|
| 46 |
+
```
|
| 47 |
+
"""
|
| 48 |
+
|
| 49 |
+
model_type = "cohere2"
|
| 50 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 51 |
+
base_model_tp_plan = {
|
| 52 |
+
"layers.*.self_attn.q_proj": "colwise",
|
| 53 |
+
"layers.*.self_attn.k_proj": "colwise",
|
| 54 |
+
"layers.*.self_attn.v_proj": "colwise",
|
| 55 |
+
"layers.*.self_attn.o_proj": "rowwise",
|
| 56 |
+
"layers.*.mlp.gate_proj": "colwise",
|
| 57 |
+
"layers.*.mlp.up_proj": "colwise",
|
| 58 |
+
"layers.*.mlp.down_proj": "rowwise",
|
| 59 |
+
}
|
| 60 |
+
base_model_pp_plan = {
|
| 61 |
+
"embed_tokens": (["input_ids"], ["inputs_embeds"]),
|
| 62 |
+
"layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
|
| 63 |
+
"norm": (["hidden_states"], ["hidden_states"]),
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
vocab_size: int = 256000
|
| 67 |
+
hidden_size: int = 8192
|
| 68 |
+
intermediate_size: int = 22528
|
| 69 |
+
logit_scale: float = 0.0625
|
| 70 |
+
num_hidden_layers: int = 40
|
| 71 |
+
num_attention_heads: int = 64
|
| 72 |
+
num_key_value_heads: int | None = None
|
| 73 |
+
hidden_act: str = "silu"
|
| 74 |
+
max_position_embeddings: int = 8192
|
| 75 |
+
initializer_range: float = 0.02
|
| 76 |
+
layer_norm_eps: float = 1e-5
|
| 77 |
+
use_cache: bool = True
|
| 78 |
+
pad_token_id: int | None = 0
|
| 79 |
+
bos_token_id: int | None = 5
|
| 80 |
+
eos_token_id: int | list[int] | None = 255001
|
| 81 |
+
tie_word_embeddings: bool = True
|
| 82 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 83 |
+
attention_bias: bool = False
|
| 84 |
+
attention_dropout: float | int = 0.0
|
| 85 |
+
sliding_window: int | None = 4096
|
| 86 |
+
layer_types: list[str] | None = None
|
| 87 |
+
|
| 88 |
+
def __post_init__(self, **kwargs):
|
| 89 |
+
if self.num_key_value_heads is None:
|
| 90 |
+
self.num_key_value_heads = self.num_attention_heads
|
| 91 |
+
|
| 92 |
+
# Need to specify head_dim in the config so it can be used in the attention forward functions
|
| 93 |
+
self.head_dim = self.hidden_size // self.num_attention_heads
|
| 94 |
+
|
| 95 |
+
# BC -> the pattern used to be a simple int, and it's still present in configs on the Hub
|
| 96 |
+
if self.layer_types is None:
|
| 97 |
+
# BC -> the pattern used to be a simple int, and it's still present in configs on the Hub
|
| 98 |
+
_sliding_window_pattern = kwargs.pop("sliding_window_pattern", 4)
|
| 99 |
+
self.layer_types = [
|
| 100 |
+
"sliding_attention" if bool((i + 1) % _sliding_window_pattern) else "full_attention"
|
| 101 |
+
for i in range(self.num_hidden_layers)
|
| 102 |
+
]
|
| 103 |
+
|
| 104 |
+
super().__post_init__(**kwargs)
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
__all__ = ["Cohere2Config"]
|
third_party/transformers/src/transformers/models/cohere_asr/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 the HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from typing import TYPE_CHECKING
|
| 16 |
+
|
| 17 |
+
from ...utils import _LazyModule
|
| 18 |
+
from ...utils.import_utils import define_import_structure
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
if TYPE_CHECKING:
|
| 22 |
+
from .configuration_cohere_asr import *
|
| 23 |
+
from .feature_extraction_cohere_asr import *
|
| 24 |
+
from .modeling_cohere_asr import *
|
| 25 |
+
from .processing_cohere_asr import *
|
| 26 |
+
else:
|
| 27 |
+
import sys
|
| 28 |
+
|
| 29 |
+
_file = globals()["__file__"]
|
| 30 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/cohere_asr/configuration_cohere_asr.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 the HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from huggingface_hub.dataclasses import strict
|
| 16 |
+
|
| 17 |
+
from ...configuration_utils import PreTrainedConfig
|
| 18 |
+
from ...utils import auto_docstring
|
| 19 |
+
from ..auto import CONFIG_MAPPING
|
| 20 |
+
from ..parakeet.configuration_parakeet import ParakeetEncoderConfig
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
@auto_docstring(checkpoint="CohereLabs/cohere-transcribe-03-2026")
|
| 24 |
+
@strict
|
| 25 |
+
class CohereAsrConfig(PreTrainedConfig):
|
| 26 |
+
r"""
|
| 27 |
+
Example:
|
| 28 |
+
|
| 29 |
+
```python
|
| 30 |
+
>>> from transformers import CohereAsrForConditionalGeneration, CohereAsrConfig
|
| 31 |
+
|
| 32 |
+
>>> configuration = CohereAsrConfig()
|
| 33 |
+
>>> model = CohereAsrForConditionalGeneration(configuration)
|
| 34 |
+
>>> configuration = model.config
|
| 35 |
+
```"""
|
| 36 |
+
|
| 37 |
+
model_type = "cohere_asr"
|
| 38 |
+
sub_configs = {"encoder_config": ParakeetEncoderConfig}
|
| 39 |
+
|
| 40 |
+
_default_encoder_config_kwargs = {
|
| 41 |
+
"hidden_size": 1280,
|
| 42 |
+
"num_hidden_layers": 48,
|
| 43 |
+
"num_attention_heads": 8,
|
| 44 |
+
"intermediate_size": 5120,
|
| 45 |
+
"hidden_act": "silu",
|
| 46 |
+
"attention_bias": True,
|
| 47 |
+
"convolution_bias": True,
|
| 48 |
+
"conv_kernel_size": 9,
|
| 49 |
+
"subsampling_factor": 8,
|
| 50 |
+
"subsampling_conv_channels": 256,
|
| 51 |
+
"num_mel_bins": 128,
|
| 52 |
+
"subsampling_conv_kernel_size": 3,
|
| 53 |
+
"subsampling_conv_stride": 2,
|
| 54 |
+
"dropout": 0.0,
|
| 55 |
+
"dropout_positions": 0.0,
|
| 56 |
+
"layerdrop": 0.0,
|
| 57 |
+
"activation_dropout": 0.0,
|
| 58 |
+
"attention_dropout": 0.0,
|
| 59 |
+
"max_position_embeddings": 5000,
|
| 60 |
+
"scale_input": False,
|
| 61 |
+
"initializer_range": 0.02,
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
encoder_config: dict | PreTrainedConfig | None = None
|
| 65 |
+
vocab_size: int = 16384
|
| 66 |
+
hidden_size: int = 1024
|
| 67 |
+
num_hidden_layers: int = 8
|
| 68 |
+
num_attention_heads: int = 8
|
| 69 |
+
num_key_value_heads: int | None = None
|
| 70 |
+
intermediate_size: int = 4096
|
| 71 |
+
hidden_act: str = "relu"
|
| 72 |
+
max_position_embeddings: int = 1024
|
| 73 |
+
pad_token_id: int | None = 2
|
| 74 |
+
eos_token_id: int | None = 3
|
| 75 |
+
bos_token_id: int | None = 4
|
| 76 |
+
is_encoder_decoder: bool = True
|
| 77 |
+
initializer_range: float = 0.02
|
| 78 |
+
attention_dropout: float | int = 0.0
|
| 79 |
+
attention_bias: bool = True
|
| 80 |
+
decoder_start_token_id: int | None = None
|
| 81 |
+
tie_word_embeddings: bool = False
|
| 82 |
+
head_dim: int | None = None
|
| 83 |
+
|
| 84 |
+
def __post_init__(self, **kwargs):
|
| 85 |
+
if self.head_dim is None:
|
| 86 |
+
self.head_dim = self.hidden_size // self.num_attention_heads
|
| 87 |
+
if self.num_key_value_heads is None:
|
| 88 |
+
self.num_key_value_heads = self.num_attention_heads
|
| 89 |
+
|
| 90 |
+
if isinstance(self.encoder_config, dict):
|
| 91 |
+
self.encoder_config["model_type"] = self.encoder_config.get("model_type", "parakeet_encoder")
|
| 92 |
+
self.encoder_config = CONFIG_MAPPING[self.encoder_config["model_type"]](
|
| 93 |
+
**{**self._default_encoder_config_kwargs, **self.encoder_config}
|
| 94 |
+
)
|
| 95 |
+
elif self.encoder_config is None:
|
| 96 |
+
self.encoder_config = CONFIG_MAPPING["parakeet_encoder"](**self._default_encoder_config_kwargs)
|
| 97 |
+
|
| 98 |
+
super().__post_init__(**kwargs)
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
__all__ = ["CohereAsrConfig"]
|
third_party/transformers/src/transformers/models/cohere_asr/feature_extraction_cohere_asr.py
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import numpy as np
|
| 16 |
+
import torch
|
| 17 |
+
|
| 18 |
+
from ...feature_extraction_sequence_utils import SequenceFeatureExtractor
|
| 19 |
+
from ...feature_extraction_utils import BatchFeature
|
| 20 |
+
from ...utils import TensorType, is_librosa_available, logging
|
| 21 |
+
from ...utils.import_utils import requires
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
if is_librosa_available():
|
| 25 |
+
import librosa
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
EPSILON = 1e-5
|
| 29 |
+
LOG_ZERO_GUARD_VALUE = 2**-24
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
logger = logging.get_logger(__name__)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
@requires(backends=("torch", "librosa"))
|
| 36 |
+
class CohereAsrFeatureExtractor(SequenceFeatureExtractor):
|
| 37 |
+
r"""
|
| 38 |
+
Constructs a CohereAsr feature extractor.
|
| 39 |
+
|
| 40 |
+
This feature extractor inherits from [`~feature_extraction_sequence_utils.SequenceFeatureExtractor`] which contains
|
| 41 |
+
most of the main methods. Users should refer to this superclass for more information regarding those methods.
|
| 42 |
+
|
| 43 |
+
This class extracts mel-filter bank features from raw speech using a custom numpy implementation of the `Short Time
|
| 44 |
+
Fourier Transform` which should match pytorch's `torch.stft` equivalent.
|
| 45 |
+
|
| 46 |
+
Args:
|
| 47 |
+
feature_size (`int`, *optional*, defaults to 128):
|
| 48 |
+
The feature dimension of the extracted features.
|
| 49 |
+
sampling_rate (`int`, *optional*, defaults to 16000):
|
| 50 |
+
The sampling rate at which the audio files should be digitalized expressed in hertz (Hz).
|
| 51 |
+
hop_length (`int`, *optional*, defaults to 160):
|
| 52 |
+
Length of the overlapping windows for the STFT used to obtain the Mel Frequency coefficients.
|
| 53 |
+
n_fft (`int`, *optional*, defaults to 512):
|
| 54 |
+
Size of the Fourier transform.
|
| 55 |
+
win_length (`int`, *optional*, defaults to 400):
|
| 56 |
+
The window length for the STFT computation.
|
| 57 |
+
preemphasis (`float`, *optional*, defaults to 0.97):
|
| 58 |
+
A preemphasis filter coefficient. 0.0 means no preemphasis filter.
|
| 59 |
+
padding_value (`float`, *optional*, defaults to 0.0):
|
| 60 |
+
Padding value used to pad the audio. Should correspond to silences.
|
| 61 |
+
dither (`float`, *optional*, defaults to 1e-05):
|
| 62 |
+
Amount of deterministic dither noise to add before feature extraction. Each sample is seeded by its
|
| 63 |
+
valid waveform length so that dither is batch-composition invariant. Set to 0.0 to disable.
|
| 64 |
+
max_audio_clip_s (`float`, *optional*, defaults to 35.0):
|
| 65 |
+
Maximum duration in seconds for a single audio chunk. Audio longer than
|
| 66 |
+
`max_audio_clip_s - overlap_chunk_second` is split at energy-based boundaries.
|
| 67 |
+
overlap_chunk_second (`float`, *optional*, defaults to 5.0):
|
| 68 |
+
Size in seconds of the boundary search window used when splitting long audio. This is not actual
|
| 69 |
+
overlap between chunks — it defines how far back from the chunk boundary to search for a quiet
|
| 70 |
+
split point.
|
| 71 |
+
min_energy_window_samples (`int`, *optional*, defaults to 1600):
|
| 72 |
+
Size in samples of the sliding window used to find the quietest point when splitting audio chunks.
|
| 73 |
+
"""
|
| 74 |
+
|
| 75 |
+
model_input_names = ["input_features", "attention_mask"]
|
| 76 |
+
|
| 77 |
+
def __init__(
|
| 78 |
+
self,
|
| 79 |
+
feature_size=128,
|
| 80 |
+
sampling_rate=16000,
|
| 81 |
+
hop_length=160,
|
| 82 |
+
n_fft=512,
|
| 83 |
+
win_length=400,
|
| 84 |
+
preemphasis=0.97,
|
| 85 |
+
padding_value=0.0,
|
| 86 |
+
dither=1e-5,
|
| 87 |
+
max_audio_clip_s=35.0,
|
| 88 |
+
overlap_chunk_second=5.0,
|
| 89 |
+
min_energy_window_samples=1600,
|
| 90 |
+
**kwargs,
|
| 91 |
+
):
|
| 92 |
+
super().__init__(feature_size=feature_size, sampling_rate=sampling_rate, padding_value=padding_value, **kwargs)
|
| 93 |
+
|
| 94 |
+
self.hop_length = hop_length
|
| 95 |
+
self.n_fft = n_fft
|
| 96 |
+
self.win_length = win_length
|
| 97 |
+
self.preemphasis = preemphasis
|
| 98 |
+
self.dither = dither
|
| 99 |
+
self.max_audio_clip_s = max_audio_clip_s
|
| 100 |
+
self.overlap_chunk_second = overlap_chunk_second
|
| 101 |
+
self.min_energy_window_samples = min_energy_window_samples
|
| 102 |
+
|
| 103 |
+
# TODO: @eustlb, for now we use librosa to compute the mel filters
|
| 104 |
+
# indeed mel_filter_bank uses np.float64 (while librosa uses np.float32), giving numerical differences
|
| 105 |
+
mel_filters = librosa.filters.mel(
|
| 106 |
+
sr=sampling_rate, n_fft=n_fft, n_mels=feature_size, fmin=0.0, fmax=sampling_rate / 2, norm="slaney"
|
| 107 |
+
)
|
| 108 |
+
self.mel_filters = torch.from_numpy(mel_filters).to(torch.float32)
|
| 109 |
+
|
| 110 |
+
def _find_split_point_energy(self, waveform: torch.Tensor, start_idx: int, end_idx: int) -> int:
|
| 111 |
+
segment = waveform[start_idx:end_idx]
|
| 112 |
+
if segment.shape[0] <= self.min_energy_window_samples:
|
| 113 |
+
return (start_idx + end_idx) // 2
|
| 114 |
+
|
| 115 |
+
min_energy = float("inf")
|
| 116 |
+
quietest_idx = start_idx
|
| 117 |
+
upper = segment.shape[0] - self.min_energy_window_samples
|
| 118 |
+
for i in range(0, upper, self.min_energy_window_samples):
|
| 119 |
+
window = segment[i : i + self.min_energy_window_samples]
|
| 120 |
+
energy = torch.sqrt(torch.mean(window * window)).item()
|
| 121 |
+
if energy < min_energy:
|
| 122 |
+
min_energy = energy
|
| 123 |
+
quietest_idx = start_idx + i
|
| 124 |
+
return quietest_idx
|
| 125 |
+
|
| 126 |
+
def _split_audio_chunks_energy(self, waveform: torch.Tensor) -> list[torch.Tensor]:
|
| 127 |
+
chunk_size = max(1, int(round(self.max_audio_clip_s * self.sampling_rate)))
|
| 128 |
+
boundary_context_size = max(1, int(round(self.overlap_chunk_second * self.sampling_rate)))
|
| 129 |
+
total_samples = waveform.shape[0]
|
| 130 |
+
|
| 131 |
+
if total_samples <= chunk_size:
|
| 132 |
+
return [waveform]
|
| 133 |
+
|
| 134 |
+
chunks_meta: list[tuple[int, int]] = []
|
| 135 |
+
idx = 0
|
| 136 |
+
while idx < total_samples:
|
| 137 |
+
if idx + chunk_size >= total_samples:
|
| 138 |
+
chunks_meta.append((idx, total_samples))
|
| 139 |
+
break
|
| 140 |
+
|
| 141 |
+
search_start = max(idx, idx + chunk_size - boundary_context_size)
|
| 142 |
+
search_end = min(idx + chunk_size, total_samples)
|
| 143 |
+
if search_end <= search_start:
|
| 144 |
+
split_point = idx + chunk_size
|
| 145 |
+
else:
|
| 146 |
+
split_point = self._find_split_point_energy(waveform, search_start, search_end)
|
| 147 |
+
|
| 148 |
+
split_point = max(idx + 1, min(split_point, total_samples))
|
| 149 |
+
chunks_meta.append((idx, split_point))
|
| 150 |
+
idx = split_point
|
| 151 |
+
|
| 152 |
+
return [waveform[start:end] for start, end in chunks_meta if end > start]
|
| 153 |
+
|
| 154 |
+
def _apply_dither(self, waveform: torch.Tensor, audio_lengths: torch.Tensor) -> torch.Tensor:
|
| 155 |
+
if self.dither <= 0:
|
| 156 |
+
return waveform
|
| 157 |
+
generator = torch.Generator(device=waveform.device)
|
| 158 |
+
for i in range(waveform.shape[0]):
|
| 159 |
+
valid_samples = min(int(audio_lengths[i].item()), waveform.shape[1])
|
| 160 |
+
if valid_samples <= 0:
|
| 161 |
+
continue
|
| 162 |
+
generator.manual_seed(valid_samples)
|
| 163 |
+
noise = torch.randn(valid_samples, dtype=waveform.dtype, device=waveform.device, generator=generator)
|
| 164 |
+
waveform[i, :valid_samples] += self.dither * noise
|
| 165 |
+
return waveform
|
| 166 |
+
|
| 167 |
+
def _torch_extract_fbank_features(self, waveform, device="cpu"):
|
| 168 |
+
# spectrogram
|
| 169 |
+
window = torch.hann_window(self.win_length, periodic=False, device=device)
|
| 170 |
+
stft = torch.stft(
|
| 171 |
+
waveform,
|
| 172 |
+
self.n_fft,
|
| 173 |
+
hop_length=self.hop_length,
|
| 174 |
+
win_length=self.win_length,
|
| 175 |
+
window=window,
|
| 176 |
+
return_complex=True,
|
| 177 |
+
pad_mode="constant",
|
| 178 |
+
)
|
| 179 |
+
# Let's match original implementation
|
| 180 |
+
magnitudes = torch.view_as_real(stft)
|
| 181 |
+
magnitudes = torch.sqrt(magnitudes.pow(2).sum(-1))
|
| 182 |
+
magnitudes = magnitudes.pow(2)
|
| 183 |
+
|
| 184 |
+
# log mel spectrogram
|
| 185 |
+
mel_filters = self.mel_filters.to(device)
|
| 186 |
+
mel_spec = mel_filters @ magnitudes
|
| 187 |
+
mel_spec = torch.log(mel_spec + LOG_ZERO_GUARD_VALUE)
|
| 188 |
+
|
| 189 |
+
# (batch_size, num_mel_filters, num_frames) -> (batch_size, num_frames, num_mel_filters)
|
| 190 |
+
mel_spec = mel_spec.permute(0, 2, 1)
|
| 191 |
+
|
| 192 |
+
return mel_spec
|
| 193 |
+
|
| 194 |
+
def __call__(
|
| 195 |
+
self,
|
| 196 |
+
raw_speech: np.ndarray | list[float] | list[np.ndarray] | list[list[float]],
|
| 197 |
+
truncation: bool = False,
|
| 198 |
+
pad_to_multiple_of: int | None = None,
|
| 199 |
+
return_tensors: str | TensorType | None = None,
|
| 200 |
+
return_attention_mask: bool | None = None,
|
| 201 |
+
padding: str | None = "longest",
|
| 202 |
+
max_length: int | None = None,
|
| 203 |
+
sampling_rate: int | None = None,
|
| 204 |
+
do_normalize: bool | None = None,
|
| 205 |
+
device: str | None = "cpu",
|
| 206 |
+
return_token_timestamps: bool | None = None,
|
| 207 |
+
**kwargs,
|
| 208 |
+
) -> BatchFeature:
|
| 209 |
+
"""
|
| 210 |
+
Main method to featurize and prepare for the model one or several sequence(s). Implementation uses PyTorch for
|
| 211 |
+
the STFT computation if available, otherwise a slower NumPy based one.
|
| 212 |
+
|
| 213 |
+
Args:
|
| 214 |
+
raw_speech (`np.ndarray`, `list[float]`, `list[np.ndarray]`, `list[list[float]]`):
|
| 215 |
+
The sequence or batch of sequences to be padded. Each sequence can be a numpy array, a list of float
|
| 216 |
+
values, a list of numpy arrays or a list of list of float values. Must be mono channel audio, not
|
| 217 |
+
stereo, i.e. single float per timestep.
|
| 218 |
+
truncation (`bool`, *optional*, default to `True`):
|
| 219 |
+
Activates truncation to cut input sequences longer than *max_length* to *max_length*.
|
| 220 |
+
pad_to_multiple_of (`int`, *optional*, defaults to None):
|
| 221 |
+
If set will pad the sequence to a multiple of the provided value.
|
| 222 |
+
|
| 223 |
+
This is especially useful to enable the use of Tensor Cores on NVIDIA hardware with compute capability
|
| 224 |
+
`>= 7.5` (Volta), or on TPUs which benefit from having sequence lengths be a multiple of 128.
|
| 225 |
+
return_attention_mask (`bool`, *optional*):
|
| 226 |
+
Whether to return the attention mask. If left to the default, will return the attention mask according
|
| 227 |
+
to the specific feature_extractor's default.
|
| 228 |
+
|
| 229 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 230 |
+
|
| 231 |
+
<Tip>
|
| 232 |
+
|
| 233 |
+
For CohereAsr models, `attention_mask` should always be passed for batched inference, to avoid subtle
|
| 234 |
+
bugs.
|
| 235 |
+
|
| 236 |
+
</Tip>
|
| 237 |
+
|
| 238 |
+
return_tensors (`str` or [`~utils.TensorType`], *optional*):
|
| 239 |
+
If set, will return tensors instead of list of python integers. Acceptable values are:
|
| 240 |
+
|
| 241 |
+
- `'tf'`: Return TensorFlow `tf.constant` objects.
|
| 242 |
+
- `'pt'`: Return PyTorch `torch.Tensor` objects.
|
| 243 |
+
- `'np'`: Return Numpy `np.ndarray` objects.
|
| 244 |
+
sampling_rate (`int`, *optional*):
|
| 245 |
+
The sampling rate at which the `raw_speech` input was sampled. It is strongly recommended to pass
|
| 246 |
+
`sampling_rate` at the forward call to prevent silent errors and allow automatic speech recognition
|
| 247 |
+
pipeline.
|
| 248 |
+
padding_value (`float`, *optional*, defaults to 0.0):
|
| 249 |
+
The value that is used to fill the padding values / vectors.
|
| 250 |
+
do_normalize (`bool`, *optional*, defaults to `False`):
|
| 251 |
+
Whether or not to zero-mean unit-variance normalize the input. Normalizing can help to significantly
|
| 252 |
+
improve the performance of the model.
|
| 253 |
+
device (`str`, *optional*, defaults to `'cpu'`):
|
| 254 |
+
Specifies the device for computation of the log-mel spectrogram of audio signals in the
|
| 255 |
+
`_torch_extract_fbank_features` method. (e.g., "cpu", "cuda")
|
| 256 |
+
return_token_timestamps (`bool`, *optional*, defaults to `None`):
|
| 257 |
+
Deprecated. Use `return_attention_mask` instead from which the number of frames can be inferred.
|
| 258 |
+
|
| 259 |
+
Whether or not to return the number of frames of the input raw_speech.
|
| 260 |
+
These num_frames can be used by the model to compute word level timestamps.
|
| 261 |
+
"""
|
| 262 |
+
if sampling_rate is not None:
|
| 263 |
+
if sampling_rate != self.sampling_rate:
|
| 264 |
+
raise ValueError(
|
| 265 |
+
f"The model corresponding to this feature extractor: {self.__class__.__name__} was trained using a"
|
| 266 |
+
f" sampling rate of {self.sampling_rate}. Please make sure that the provided `raw_speech` input"
|
| 267 |
+
f" was sampled with {self.sampling_rate} and not {sampling_rate}."
|
| 268 |
+
)
|
| 269 |
+
else:
|
| 270 |
+
logger.warning(
|
| 271 |
+
f"It is strongly recommended to pass the `sampling_rate` argument to `{self.__class__.__name__}()`. "
|
| 272 |
+
"Failing to do so can result in silent errors that might be hard to debug."
|
| 273 |
+
)
|
| 274 |
+
|
| 275 |
+
# Convert to torch tensor
|
| 276 |
+
if isinstance(raw_speech, np.ndarray):
|
| 277 |
+
raw_speech = torch.tensor(raw_speech)
|
| 278 |
+
elif isinstance(raw_speech, (list, tuple)) and isinstance(raw_speech[0], np.ndarray):
|
| 279 |
+
raw_speech = [torch.tensor(speech) for speech in raw_speech]
|
| 280 |
+
|
| 281 |
+
is_batched_torch = isinstance(raw_speech, torch.Tensor) and len(raw_speech.shape) > 1
|
| 282 |
+
if is_batched_torch and len(raw_speech.shape) > 2:
|
| 283 |
+
logger.warning(
|
| 284 |
+
f"Only mono-channel audio is supported for input to {self.__class__.__name__}. "
|
| 285 |
+
"We will take the mean of the channels to convert to mono."
|
| 286 |
+
)
|
| 287 |
+
raw_speech = raw_speech.mean(-1)
|
| 288 |
+
|
| 289 |
+
is_batched_sequence = isinstance(raw_speech, (list, tuple))
|
| 290 |
+
if is_batched_sequence:
|
| 291 |
+
for speech in raw_speech:
|
| 292 |
+
if len(speech.shape) > 1:
|
| 293 |
+
logger.warning(
|
| 294 |
+
f"Only mono-channel audio is supported for input to {self.__class__.__name__}. "
|
| 295 |
+
"We will take the mean of the channels to convert to mono."
|
| 296 |
+
)
|
| 297 |
+
speech = speech.mean(-1)
|
| 298 |
+
|
| 299 |
+
if is_batched_torch or is_batched_sequence:
|
| 300 |
+
raw_speech = [speech.to(torch.float32) for speech in raw_speech]
|
| 301 |
+
else:
|
| 302 |
+
raw_speech = [raw_speech.to(torch.float32)]
|
| 303 |
+
|
| 304 |
+
# Chunk long audio at energy-based boundaries
|
| 305 |
+
fast_path_threshold_s = max(0.0, self.max_audio_clip_s - self.overlap_chunk_second)
|
| 306 |
+
audio_chunk_index: list[tuple[int, int | None]] = []
|
| 307 |
+
chunked_speech: list[torch.Tensor] = []
|
| 308 |
+
for sample_idx, speech in enumerate(raw_speech):
|
| 309 |
+
duration_s = speech.shape[0] / self.sampling_rate
|
| 310 |
+
if duration_s <= fast_path_threshold_s:
|
| 311 |
+
chunked_speech.append(speech)
|
| 312 |
+
audio_chunk_index.append((sample_idx, None))
|
| 313 |
+
else:
|
| 314 |
+
chunks = self._split_audio_chunks_energy(speech)
|
| 315 |
+
for chunk_idx, chunk in enumerate(chunks):
|
| 316 |
+
chunked_speech.append(chunk)
|
| 317 |
+
audio_chunk_index.append((sample_idx, chunk_idx))
|
| 318 |
+
|
| 319 |
+
raw_speech = [speech[:, None] for speech in chunked_speech]
|
| 320 |
+
|
| 321 |
+
audio_lengths = [len(speech) for speech in raw_speech]
|
| 322 |
+
batched_speech = BatchFeature({"input_features": raw_speech, "audio_lengths": audio_lengths})
|
| 323 |
+
|
| 324 |
+
padded_inputs = self.pad(
|
| 325 |
+
batched_speech,
|
| 326 |
+
padding=padding,
|
| 327 |
+
max_length=max_length,
|
| 328 |
+
truncation=truncation,
|
| 329 |
+
pad_to_multiple_of=pad_to_multiple_of,
|
| 330 |
+
return_tensors="pt",
|
| 331 |
+
)
|
| 332 |
+
input_features = padded_inputs.input_features.squeeze(-1)
|
| 333 |
+
|
| 334 |
+
# dithering
|
| 335 |
+
input_features = self._apply_dither(input_features, padded_inputs.audio_lengths)
|
| 336 |
+
|
| 337 |
+
# preemphasis
|
| 338 |
+
if self.preemphasis is not None:
|
| 339 |
+
timemask = torch.arange(input_features.shape[1], device=input_features.device).unsqueeze(
|
| 340 |
+
0
|
| 341 |
+
) < padded_inputs.audio_lengths.unsqueeze(1)
|
| 342 |
+
input_features = torch.cat(
|
| 343 |
+
[input_features[:, :1], input_features[:, 1:] - self.preemphasis * input_features[:, :-1]], dim=1
|
| 344 |
+
)
|
| 345 |
+
input_features = input_features.masked_fill(~timemask, 0.0)
|
| 346 |
+
|
| 347 |
+
input_features = self._torch_extract_fbank_features(input_features, device)
|
| 348 |
+
features_lengths = torch.floor_divide(
|
| 349 |
+
padded_inputs.audio_lengths + self.n_fft // 2 * 2 - self.n_fft, self.hop_length
|
| 350 |
+
)
|
| 351 |
+
attention_mask = torch.arange(input_features.shape[1], device=device)[None, :] < features_lengths[:, None]
|
| 352 |
+
|
| 353 |
+
# normalize mel features, ignoring padding
|
| 354 |
+
mask = attention_mask.unsqueeze(-1)
|
| 355 |
+
input_features_masked = input_features * mask
|
| 356 |
+
mean = input_features_masked.sum(dim=1) / features_lengths.unsqueeze(-1)
|
| 357 |
+
mean = mean.unsqueeze(1)
|
| 358 |
+
variance = ((input_features_masked - mean) ** 2 * mask).sum(dim=1) / (features_lengths - 1).unsqueeze(-1)
|
| 359 |
+
std = torch.sqrt(variance).unsqueeze(1)
|
| 360 |
+
input_features = (input_features - mean) / (std + EPSILON)
|
| 361 |
+
input_features *= mask
|
| 362 |
+
|
| 363 |
+
result = BatchFeature(
|
| 364 |
+
data={
|
| 365 |
+
"input_features": input_features,
|
| 366 |
+
"attention_mask": attention_mask,
|
| 367 |
+
},
|
| 368 |
+
tensor_type=return_tensors,
|
| 369 |
+
)
|
| 370 |
+
result["audio_chunk_index"] = audio_chunk_index
|
| 371 |
+
return result
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
__all__ = ["CohereAsrFeatureExtractor"]
|
third_party/transformers/src/transformers/models/cohere_asr/modeling_cohere_asr.py
ADDED
|
@@ -0,0 +1,658 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/cohere_asr/modular_cohere_asr.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_cohere_asr.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2026 the HuggingFace Team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from collections.abc import Callable
|
| 22 |
+
|
| 23 |
+
import torch
|
| 24 |
+
import torch.nn as nn
|
| 25 |
+
|
| 26 |
+
from ...activations import ACT2FN
|
| 27 |
+
from ...cache_utils import Cache, DynamicCache, EncoderDecoderCache
|
| 28 |
+
from ...generation import GenerationMixin
|
| 29 |
+
from ...masking_utils import create_bidirectional_mask, create_causal_mask
|
| 30 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 31 |
+
from ...modeling_outputs import (
|
| 32 |
+
BaseModelOutput,
|
| 33 |
+
BaseModelOutputWithPastAndCrossAttentions,
|
| 34 |
+
Seq2SeqLMOutput,
|
| 35 |
+
Seq2SeqModelOutput,
|
| 36 |
+
)
|
| 37 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 38 |
+
from ...processing_utils import Unpack
|
| 39 |
+
from ...utils import TransformersKwargs, auto_docstring
|
| 40 |
+
from ...utils.generic import can_return_tuple, merge_with_config_defaults
|
| 41 |
+
from ...utils.output_capturing import OutputRecorder, capture_outputs
|
| 42 |
+
from ..auto.modeling_auto import AutoModel
|
| 43 |
+
from .configuration_cohere_asr import CohereAsrConfig
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class CohereAsrDecoderMLP(nn.Module):
|
| 47 |
+
def __init__(self, config):
|
| 48 |
+
super().__init__()
|
| 49 |
+
self.config = config
|
| 50 |
+
self.activation_fn = ACT2FN[config.hidden_act]
|
| 51 |
+
self.fc1 = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 52 |
+
self.fc2 = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 53 |
+
|
| 54 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 55 |
+
hidden_states = self.fc1(hidden_states)
|
| 56 |
+
hidden_states = self.activation_fn(hidden_states)
|
| 57 |
+
hidden_states = self.fc2(hidden_states)
|
| 58 |
+
return hidden_states
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 62 |
+
"""
|
| 63 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 64 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 65 |
+
"""
|
| 66 |
+
batch, num_key_value_heads, slen, head_dim = hidden_states.shape
|
| 67 |
+
if n_rep == 1:
|
| 68 |
+
return hidden_states
|
| 69 |
+
hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
|
| 70 |
+
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def eager_attention_forward(
|
| 74 |
+
module: nn.Module,
|
| 75 |
+
query: torch.Tensor,
|
| 76 |
+
key: torch.Tensor,
|
| 77 |
+
value: torch.Tensor,
|
| 78 |
+
attention_mask: torch.Tensor | None,
|
| 79 |
+
scaling: float,
|
| 80 |
+
dropout: float = 0.0,
|
| 81 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 82 |
+
):
|
| 83 |
+
key_states = repeat_kv(key, module.num_key_value_groups)
|
| 84 |
+
value_states = repeat_kv(value, module.num_key_value_groups)
|
| 85 |
+
|
| 86 |
+
attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
|
| 87 |
+
if attention_mask is not None:
|
| 88 |
+
attn_weights = attn_weights + attention_mask
|
| 89 |
+
|
| 90 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
|
| 91 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 92 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 93 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 94 |
+
|
| 95 |
+
return attn_output, attn_weights
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
# Modular automatically inherits RoPE, hence no inheritance for now
|
| 99 |
+
class CohereAsrSelfAttention(nn.Module):
|
| 100 |
+
def __init__(self, config: CohereAsrConfig, layer_idx: int):
|
| 101 |
+
super().__init__()
|
| 102 |
+
self.config = config
|
| 103 |
+
self.layer_idx = layer_idx
|
| 104 |
+
self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
|
| 105 |
+
self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
|
| 106 |
+
self.scaling = self.head_dim**-0.5
|
| 107 |
+
self.attention_dropout = config.attention_dropout
|
| 108 |
+
self.is_causal = True
|
| 109 |
+
|
| 110 |
+
self.q_proj = nn.Linear(
|
| 111 |
+
config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
|
| 112 |
+
)
|
| 113 |
+
self.k_proj = nn.Linear(
|
| 114 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 115 |
+
)
|
| 116 |
+
self.v_proj = nn.Linear(
|
| 117 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 118 |
+
)
|
| 119 |
+
self.o_proj = nn.Linear(
|
| 120 |
+
config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
def forward(
|
| 124 |
+
self,
|
| 125 |
+
hidden_states: torch.Tensor,
|
| 126 |
+
attention_mask: torch.Tensor,
|
| 127 |
+
past_key_values: Cache | None = None,
|
| 128 |
+
**kwargs,
|
| 129 |
+
):
|
| 130 |
+
input_shape = hidden_states.shape[:-1]
|
| 131 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 132 |
+
|
| 133 |
+
query_states = self.q_proj(hidden_states)
|
| 134 |
+
key_states = self.k_proj(hidden_states)
|
| 135 |
+
value_states = self.v_proj(hidden_states)
|
| 136 |
+
|
| 137 |
+
query_states = query_states.view(hidden_shape).transpose(1, 2)
|
| 138 |
+
key_states = key_states.view(hidden_shape).transpose(1, 2)
|
| 139 |
+
value_states = value_states.view(hidden_shape).transpose(1, 2)
|
| 140 |
+
|
| 141 |
+
if past_key_values is not None:
|
| 142 |
+
past_key_values = past_key_values.self_attention_cache
|
| 143 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 144 |
+
|
| 145 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 146 |
+
self.config._attn_implementation, eager_attention_forward
|
| 147 |
+
)
|
| 148 |
+
|
| 149 |
+
attn_output, attn_weights = attention_interface(
|
| 150 |
+
self,
|
| 151 |
+
query_states,
|
| 152 |
+
key_states,
|
| 153 |
+
value_states,
|
| 154 |
+
attention_mask,
|
| 155 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 156 |
+
scaling=self.scaling,
|
| 157 |
+
**kwargs,
|
| 158 |
+
)
|
| 159 |
+
|
| 160 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 161 |
+
attn_output = self.o_proj(attn_output)
|
| 162 |
+
return attn_output, attn_weights
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
# Modular automatically inherits RoPE, hence no inheritance for now
|
| 166 |
+
class CohereAsrCrossAttention(nn.Module):
|
| 167 |
+
def __init__(self, config: CohereAsrConfig, layer_idx: int):
|
| 168 |
+
super().__init__()
|
| 169 |
+
self.config = config
|
| 170 |
+
self.layer_idx = layer_idx
|
| 171 |
+
self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
|
| 172 |
+
self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
|
| 173 |
+
self.scaling = self.head_dim**-0.5
|
| 174 |
+
self.attention_dropout = config.attention_dropout
|
| 175 |
+
self.is_causal = False
|
| 176 |
+
|
| 177 |
+
self.q_proj = nn.Linear(
|
| 178 |
+
config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
|
| 179 |
+
)
|
| 180 |
+
self.k_proj = nn.Linear(
|
| 181 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 182 |
+
)
|
| 183 |
+
self.v_proj = nn.Linear(
|
| 184 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 185 |
+
)
|
| 186 |
+
self.o_proj = nn.Linear(
|
| 187 |
+
config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
|
| 188 |
+
)
|
| 189 |
+
|
| 190 |
+
def forward(
|
| 191 |
+
self,
|
| 192 |
+
hidden_states: torch.Tensor,
|
| 193 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 194 |
+
attention_mask: torch.Tensor | None = None,
|
| 195 |
+
past_key_values: Cache | None = None,
|
| 196 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 197 |
+
):
|
| 198 |
+
# determine input shapes
|
| 199 |
+
bsz, tgt_len = hidden_states.shape[:-1]
|
| 200 |
+
src_len = encoder_hidden_states.shape[1]
|
| 201 |
+
|
| 202 |
+
q_input_shape = (bsz, tgt_len, -1, self.head_dim)
|
| 203 |
+
kv_input_shape = (bsz, src_len, -1, self.head_dim)
|
| 204 |
+
|
| 205 |
+
# get query proj
|
| 206 |
+
query_states = self.q_proj(hidden_states).view(*q_input_shape).transpose(1, 2)
|
| 207 |
+
|
| 208 |
+
is_updated = past_key_values.is_updated.get(self.layer_idx) if past_key_values is not None else False
|
| 209 |
+
if past_key_values is not None and is_updated:
|
| 210 |
+
# reuse k,v, cross_attentions
|
| 211 |
+
key_states = past_key_values.cross_attention_cache.layers[self.layer_idx].keys
|
| 212 |
+
value_states = past_key_values.cross_attention_cache.layers[self.layer_idx].values
|
| 213 |
+
else:
|
| 214 |
+
key_states = self.k_proj(encoder_hidden_states).view(*kv_input_shape).transpose(1, 2)
|
| 215 |
+
value_states = self.v_proj(encoder_hidden_states).view(*kv_input_shape).transpose(1, 2)
|
| 216 |
+
|
| 217 |
+
if past_key_values is not None:
|
| 218 |
+
# save all states to the cache
|
| 219 |
+
key_states, value_states = past_key_values.cross_attention_cache.update(
|
| 220 |
+
key_states, value_states, self.layer_idx
|
| 221 |
+
)
|
| 222 |
+
# set flag that curr layer for cross-attn is already updated so we can re-use in subsequent calls
|
| 223 |
+
past_key_values.is_updated[self.layer_idx] = True
|
| 224 |
+
|
| 225 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 226 |
+
self.config._attn_implementation, eager_attention_forward
|
| 227 |
+
)
|
| 228 |
+
|
| 229 |
+
attn_output, attn_weights = attention_interface(
|
| 230 |
+
self,
|
| 231 |
+
query_states,
|
| 232 |
+
key_states,
|
| 233 |
+
value_states,
|
| 234 |
+
attention_mask,
|
| 235 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 236 |
+
scaling=self.scaling,
|
| 237 |
+
**kwargs,
|
| 238 |
+
)
|
| 239 |
+
attn_output = attn_output.reshape(bsz, tgt_len, -1).contiguous()
|
| 240 |
+
attn_output = self.o_proj(attn_output)
|
| 241 |
+
return attn_output, attn_weights
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
class CohereAsrDecoderLayer(GradientCheckpointingLayer):
|
| 245 |
+
def __init__(self, config, layer_idx=None):
|
| 246 |
+
super().__init__()
|
| 247 |
+
self.self_attn = CohereAsrSelfAttention(config=config, layer_idx=layer_idx)
|
| 248 |
+
self.encoder_attn = CohereAsrCrossAttention(config=config, layer_idx=layer_idx)
|
| 249 |
+
|
| 250 |
+
self.mlp = CohereAsrDecoderMLP(config)
|
| 251 |
+
self.input_layernorm = nn.LayerNorm(config.hidden_size)
|
| 252 |
+
self.post_attention_layernorm = nn.LayerNorm(config.hidden_size)
|
| 253 |
+
self.final_layernorm = nn.LayerNorm(config.hidden_size)
|
| 254 |
+
|
| 255 |
+
def forward(
|
| 256 |
+
self,
|
| 257 |
+
hidden_states: torch.Tensor,
|
| 258 |
+
attention_mask: torch.Tensor | None = None,
|
| 259 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 260 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 261 |
+
position_ids: torch.LongTensor | None = None,
|
| 262 |
+
encoder_position_ids: torch.LongTensor | None = None,
|
| 263 |
+
past_key_values: Cache | None = None,
|
| 264 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 265 |
+
) -> tuple[torch.FloatTensor, tuple[torch.FloatTensor, torch.FloatTensor] | None]:
|
| 266 |
+
residual = hidden_states
|
| 267 |
+
hidden_states = self.input_layernorm(hidden_states)
|
| 268 |
+
|
| 269 |
+
hidden_states, _ = self.self_attn(
|
| 270 |
+
hidden_states=hidden_states,
|
| 271 |
+
attention_mask=attention_mask,
|
| 272 |
+
position_ids=position_ids,
|
| 273 |
+
past_key_values=past_key_values,
|
| 274 |
+
**kwargs,
|
| 275 |
+
)
|
| 276 |
+
hidden_states = residual + hidden_states
|
| 277 |
+
|
| 278 |
+
if encoder_hidden_states is not None:
|
| 279 |
+
residual = hidden_states
|
| 280 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 281 |
+
hidden_states, _ = self.encoder_attn(
|
| 282 |
+
hidden_states=hidden_states,
|
| 283 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 284 |
+
attention_mask=encoder_attention_mask,
|
| 285 |
+
past_key_values=past_key_values,
|
| 286 |
+
)
|
| 287 |
+
hidden_states = residual + hidden_states
|
| 288 |
+
|
| 289 |
+
residual = hidden_states
|
| 290 |
+
hidden_states = self.final_layernorm(hidden_states)
|
| 291 |
+
hidden_states = self.mlp(hidden_states)
|
| 292 |
+
hidden_states = residual + hidden_states
|
| 293 |
+
return hidden_states
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
@auto_docstring
|
| 297 |
+
class CohereAsrPreTrainedModel(PreTrainedModel):
|
| 298 |
+
config: CohereAsrConfig
|
| 299 |
+
base_model_prefix = "model"
|
| 300 |
+
main_input_name = "input_features"
|
| 301 |
+
input_modalities = "audio"
|
| 302 |
+
supports_gradient_checkpointing = True
|
| 303 |
+
_no_split_modules = ["CohereAsrEncoderLayer", "CohereAsrDecoderLayer"]
|
| 304 |
+
_supports_flash_attn = True
|
| 305 |
+
_supports_sdpa = True
|
| 306 |
+
|
| 307 |
+
_can_compile_fullgraph = True
|
| 308 |
+
_keys_to_ignore_on_load_unexpected = [r"preprocessor\.featurizer\..*"]
|
| 309 |
+
# TODO arthur, how do we separate when it cross / self coming from different layer?
|
| 310 |
+
|
| 311 |
+
def _get_feat_extract_output_lengths(self, input_lengths: torch.LongTensor):
|
| 312 |
+
"""
|
| 313 |
+
Computes the output length of the convolutional layers
|
| 314 |
+
"""
|
| 315 |
+
output_conv1_length = int((input_lengths - 127) / 64 + 1)
|
| 316 |
+
output_conv2_length = int((output_conv1_length - 7) / 3 + 1)
|
| 317 |
+
output_conv3_length = int((output_conv2_length - 3) / 2 + 1)
|
| 318 |
+
|
| 319 |
+
return output_conv3_length
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
@auto_docstring
|
| 323 |
+
class CohereAsrDecoder(CohereAsrPreTrainedModel):
|
| 324 |
+
main_input_name = "input_ids"
|
| 325 |
+
_can_record_outputs = {
|
| 326 |
+
"attentions": OutputRecorder(CohereAsrSelfAttention, index=1, layer_name="self_attn"),
|
| 327 |
+
"hidden_states": CohereAsrDecoderLayer,
|
| 328 |
+
"cross_attentions": OutputRecorder(CohereAsrCrossAttention, index=1, layer_name="encoder_attn"),
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
def __init__(self, config):
|
| 332 |
+
super().__init__(config)
|
| 333 |
+
self.padding_idx = config.pad_token_id
|
| 334 |
+
self.vocab_size = config.vocab_size
|
| 335 |
+
|
| 336 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
|
| 337 |
+
self.layers = nn.ModuleList([CohereAsrDecoderLayer(config, idx) for idx in range(config.num_hidden_layers)])
|
| 338 |
+
self.norm = nn.LayerNorm(config.hidden_size)
|
| 339 |
+
self.gradient_checkpointing = False
|
| 340 |
+
self.pos_emb = nn.Embedding(config.max_position_embeddings, config.hidden_size)
|
| 341 |
+
self.embedding_layernorm = nn.LayerNorm(config.hidden_size)
|
| 342 |
+
self.proj = nn.Linear(config.encoder_config.hidden_size, config.hidden_size, bias=True)
|
| 343 |
+
|
| 344 |
+
# Initialize weights and apply final processing
|
| 345 |
+
self.post_init()
|
| 346 |
+
|
| 347 |
+
@merge_with_config_defaults
|
| 348 |
+
@capture_outputs
|
| 349 |
+
def forward(
|
| 350 |
+
self,
|
| 351 |
+
input_ids: torch.LongTensor | None = None,
|
| 352 |
+
attention_mask: torch.Tensor | None = None,
|
| 353 |
+
position_ids: torch.LongTensor | None = None,
|
| 354 |
+
past_key_values: Cache | None = None,
|
| 355 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 356 |
+
use_cache: bool | None = None,
|
| 357 |
+
encoder_hidden_states: torch.FloatTensor | None = None,
|
| 358 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 359 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 360 |
+
) -> tuple | BaseModelOutputWithPastAndCrossAttentions:
|
| 361 |
+
r"""
|
| 362 |
+
encoder_hidden_states (`torch.FloatTensor` of shape `(batch_size, encoder_sequence_length, hidden_size)`, *optional*):
|
| 363 |
+
Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention
|
| 364 |
+
of the decoder.
|
| 365 |
+
encoder_attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 366 |
+
Mask to avoid performing attention on padding indices in `encoder_hidden_states`. Mask values selected in `[0, 1]`:
|
| 367 |
+
- 1 for tokens that are **not masked**,
|
| 368 |
+
- 0 for tokens that are **masked**.
|
| 369 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 370 |
+
"""
|
| 371 |
+
encoder_hidden_states = self.proj(encoder_hidden_states)
|
| 372 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 373 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 374 |
+
|
| 375 |
+
if inputs_embeds is None:
|
| 376 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 377 |
+
|
| 378 |
+
if use_cache and past_key_values is None:
|
| 379 |
+
past_key_values = EncoderDecoderCache(DynamicCache(config=self.config), DynamicCache(config=self.config))
|
| 380 |
+
|
| 381 |
+
if position_ids is None:
|
| 382 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 383 |
+
position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
|
| 384 |
+
position_ids = position_ids.unsqueeze(0)
|
| 385 |
+
|
| 386 |
+
# Fixed sinusoidal position embedding added to token embeddings, then layernorm
|
| 387 |
+
pos_emb = self.pos_emb(position_ids.squeeze(0))
|
| 388 |
+
inputs_embeds = self.embedding_layernorm(inputs_embeds + pos_emb)
|
| 389 |
+
|
| 390 |
+
causal_mask = create_causal_mask(
|
| 391 |
+
config=self.config,
|
| 392 |
+
inputs_embeds=inputs_embeds,
|
| 393 |
+
attention_mask=attention_mask,
|
| 394 |
+
past_key_values=past_key_values,
|
| 395 |
+
position_ids=position_ids,
|
| 396 |
+
)
|
| 397 |
+
encoder_attention_mask = create_bidirectional_mask(
|
| 398 |
+
config=self.config,
|
| 399 |
+
inputs_embeds=inputs_embeds,
|
| 400 |
+
attention_mask=encoder_attention_mask,
|
| 401 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 402 |
+
)
|
| 403 |
+
|
| 404 |
+
hidden_states = inputs_embeds
|
| 405 |
+
for decoder_layer in self.layers:
|
| 406 |
+
hidden_states = decoder_layer(
|
| 407 |
+
hidden_states,
|
| 408 |
+
causal_mask,
|
| 409 |
+
encoder_hidden_states, # as a positional argument for gradient checkpointing
|
| 410 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 411 |
+
position_ids=position_ids,
|
| 412 |
+
past_key_values=past_key_values,
|
| 413 |
+
**kwargs,
|
| 414 |
+
)
|
| 415 |
+
|
| 416 |
+
hidden_states = self.norm(hidden_states)
|
| 417 |
+
|
| 418 |
+
return BaseModelOutputWithPastAndCrossAttentions(
|
| 419 |
+
last_hidden_state=hidden_states,
|
| 420 |
+
past_key_values=past_key_values if use_cache else None,
|
| 421 |
+
)
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
@auto_docstring
|
| 425 |
+
class CohereAsrModel(CohereAsrPreTrainedModel):
|
| 426 |
+
def __init__(self, config):
|
| 427 |
+
super().__init__(config)
|
| 428 |
+
self.encoder = AutoModel.from_config(config.encoder_config)
|
| 429 |
+
self.decoder = CohereAsrDecoder(config)
|
| 430 |
+
# Initialize weights and apply final processing
|
| 431 |
+
self.post_init()
|
| 432 |
+
|
| 433 |
+
def get_input_embeddings(self):
|
| 434 |
+
return self.decoder.embed_tokens
|
| 435 |
+
|
| 436 |
+
def set_input_embeddings(self, value):
|
| 437 |
+
self.decoder.embed_tokens = value
|
| 438 |
+
|
| 439 |
+
def freeze_encoder(self):
|
| 440 |
+
"""
|
| 441 |
+
Calling this function will disable the gradient computation for the CohereAsr encoder so that its parameters will
|
| 442 |
+
not be updated during training.
|
| 443 |
+
"""
|
| 444 |
+
self.encoder._freeze_parameters()
|
| 445 |
+
|
| 446 |
+
def _mask_input_features(self):
|
| 447 |
+
"""
|
| 448 |
+
Masks extracted features along time axis and/or along feature axis according to
|
| 449 |
+
[SpecAugment](https://huggingface.co/papers/1904.08779).
|
| 450 |
+
"""
|
| 451 |
+
raise AttributeError("Not needed for CohereAsr")
|
| 452 |
+
|
| 453 |
+
@can_return_tuple
|
| 454 |
+
@auto_docstring
|
| 455 |
+
def forward(
|
| 456 |
+
self,
|
| 457 |
+
input_features: torch.FloatTensor | None = None,
|
| 458 |
+
attention_mask: torch.LongTensor | None = None,
|
| 459 |
+
decoder_input_ids: torch.LongTensor | None = None,
|
| 460 |
+
decoder_attention_mask: torch.LongTensor | None = None,
|
| 461 |
+
encoder_outputs: tuple[tuple[torch.FloatTensor]] | None = None,
|
| 462 |
+
past_key_values: EncoderDecoderCache | None = None,
|
| 463 |
+
decoder_inputs_embeds: tuple[torch.FloatTensor] | None = None,
|
| 464 |
+
decoder_position_ids: tuple[torch.LongTensor] | None = None,
|
| 465 |
+
use_cache: bool | None = None,
|
| 466 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 467 |
+
) -> Seq2SeqModelOutput:
|
| 468 |
+
r"""
|
| 469 |
+
input_features (`torch.FloatTensor` of shape `(batch_size, audio_length)`):
|
| 470 |
+
Float values of the raw speech waveform. Raw speech waveform can be
|
| 471 |
+
obtained by loading a `.flac` or `.wav` audio file into an array of type `list[float]`, a
|
| 472 |
+
`numpy.ndarray` or a `torch.Tensor`, *e.g.* via the torchcodec library (`pip install torchcodec`) or
|
| 473 |
+
the soundfile library (`pip install soundfile`). To prepare the array into
|
| 474 |
+
`input_features`, the [`AutoFeatureExtractor`] should be used for padding
|
| 475 |
+
and conversion into a tensor of type `torch.FloatTensor`.
|
| 476 |
+
decoder_position_ids (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`):
|
| 477 |
+
Indices of positions of each input sequence tokens in the position embeddings.
|
| 478 |
+
Used to calculate the position embeddings up to `config.decoder_config.max_position_embeddings`
|
| 479 |
+
|
| 480 |
+
Example:
|
| 481 |
+
|
| 482 |
+
```python
|
| 483 |
+
>>> import torch
|
| 484 |
+
>>> from transformers import AutoFeatureExtractor, CohereAsrModel
|
| 485 |
+
>>> from datasets import load_dataset
|
| 486 |
+
|
| 487 |
+
>>> model = CohereAsrModel.from_pretrained("UsefulSensors/cohere_asr-tiny")
|
| 488 |
+
>>> feature_extractor = AutoFeatureExtractor.from_pretrained("UsefulSensors/cohere_asr-tiny")
|
| 489 |
+
>>> ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
|
| 490 |
+
>>> inputs = feature_extractor(ds[0]["audio"]["array"], return_tensors="pt")
|
| 491 |
+
>>> input_features = inputs.input_features
|
| 492 |
+
>>> decoder_input_ids = torch.tensor([[1, 1]]) * model.config.decoder_start_token_id
|
| 493 |
+
>>> last_hidden_state = model(input_features, decoder_input_ids=decoder_input_ids).last_hidden_state
|
| 494 |
+
>>> list(last_hidden_state.shape)
|
| 495 |
+
[1, 2, 288]
|
| 496 |
+
```
|
| 497 |
+
"""
|
| 498 |
+
# Main difference: uses `input_features` instead of `input_values`
|
| 499 |
+
if encoder_outputs is None:
|
| 500 |
+
encoder_outputs: BaseModelOutput = self.encoder(input_features, attention_mask=attention_mask, **kwargs)
|
| 501 |
+
|
| 502 |
+
decoder_outputs: BaseModelOutputWithPastAndCrossAttentions = self.decoder(
|
| 503 |
+
input_ids=decoder_input_ids,
|
| 504 |
+
attention_mask=decoder_attention_mask,
|
| 505 |
+
encoder_hidden_states=encoder_outputs.last_hidden_state,
|
| 506 |
+
encoder_attention_mask=encoder_outputs.attention_mask,
|
| 507 |
+
past_key_values=past_key_values,
|
| 508 |
+
inputs_embeds=decoder_inputs_embeds,
|
| 509 |
+
position_ids=decoder_position_ids,
|
| 510 |
+
use_cache=use_cache,
|
| 511 |
+
**kwargs,
|
| 512 |
+
)
|
| 513 |
+
|
| 514 |
+
return Seq2SeqModelOutput(
|
| 515 |
+
last_hidden_state=decoder_outputs.last_hidden_state,
|
| 516 |
+
past_key_values=decoder_outputs.past_key_values,
|
| 517 |
+
decoder_hidden_states=decoder_outputs.hidden_states,
|
| 518 |
+
decoder_attentions=decoder_outputs.attentions,
|
| 519 |
+
cross_attentions=decoder_outputs.cross_attentions,
|
| 520 |
+
encoder_last_hidden_state=encoder_outputs.last_hidden_state,
|
| 521 |
+
encoder_hidden_states=encoder_outputs.hidden_states,
|
| 522 |
+
encoder_attentions=encoder_outputs.attentions,
|
| 523 |
+
)
|
| 524 |
+
|
| 525 |
+
|
| 526 |
+
def shift_tokens_right(input_ids: torch.Tensor, pad_token_id: int, decoder_start_token_id: int):
|
| 527 |
+
"""
|
| 528 |
+
Shift input ids one token to the right.
|
| 529 |
+
"""
|
| 530 |
+
shifted_input_ids = input_ids.new_zeros(input_ids.shape)
|
| 531 |
+
shifted_input_ids[:, 1:] = input_ids[:, :-1].clone()
|
| 532 |
+
shifted_input_ids[:, 0] = decoder_start_token_id
|
| 533 |
+
|
| 534 |
+
if pad_token_id is None:
|
| 535 |
+
raise ValueError("self.model.config.pad_token_id has to be defined.")
|
| 536 |
+
# replace possible -100 values in labels by `pad_token_id`
|
| 537 |
+
shifted_input_ids.masked_fill_(shifted_input_ids == -100, pad_token_id)
|
| 538 |
+
|
| 539 |
+
return shifted_input_ids
|
| 540 |
+
|
| 541 |
+
|
| 542 |
+
@auto_docstring(
|
| 543 |
+
custom_intro="""
|
| 544 |
+
The CohereAsr Model with a language modeling head. Can be used for automatic speech recognition.
|
| 545 |
+
"""
|
| 546 |
+
)
|
| 547 |
+
class CohereAsrForConditionalGeneration(CohereAsrPreTrainedModel, GenerationMixin):
|
| 548 |
+
_tied_weights_keys = {"proj_out.weight": "model.decoder.embed_tokens.weight"}
|
| 549 |
+
|
| 550 |
+
def __init__(self, config):
|
| 551 |
+
super().__init__(config)
|
| 552 |
+
self.model = CohereAsrModel(config)
|
| 553 |
+
self.proj_out = nn.Linear(config.hidden_size, config.vocab_size, bias=True)
|
| 554 |
+
|
| 555 |
+
# Initialize weights and apply final processing
|
| 556 |
+
self.post_init()
|
| 557 |
+
|
| 558 |
+
def get_output_embeddings(self):
|
| 559 |
+
return self.proj_out
|
| 560 |
+
|
| 561 |
+
def set_output_embeddings(self, new_embeddings):
|
| 562 |
+
self.proj_out = new_embeddings
|
| 563 |
+
|
| 564 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 565 |
+
return self.model.get_input_embeddings()
|
| 566 |
+
|
| 567 |
+
@can_return_tuple
|
| 568 |
+
@auto_docstring
|
| 569 |
+
def forward(
|
| 570 |
+
self,
|
| 571 |
+
input_features: torch.FloatTensor | None = None,
|
| 572 |
+
attention_mask: torch.LongTensor | None = None,
|
| 573 |
+
decoder_input_ids: torch.LongTensor | None = None,
|
| 574 |
+
decoder_attention_mask: torch.LongTensor | None = None,
|
| 575 |
+
encoder_outputs: tuple[tuple[torch.FloatTensor]] | None = None,
|
| 576 |
+
past_key_values: EncoderDecoderCache | None = None,
|
| 577 |
+
decoder_inputs_embeds: tuple[torch.FloatTensor] | None = None,
|
| 578 |
+
decoder_position_ids: tuple[torch.LongTensor] | None = None,
|
| 579 |
+
use_cache: bool | None = None,
|
| 580 |
+
labels: torch.LongTensor | None = None,
|
| 581 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 582 |
+
) -> Seq2SeqLMOutput:
|
| 583 |
+
r"""
|
| 584 |
+
input_features (`torch.FloatTensor` of shape `(batch_size, audio_length)`):
|
| 585 |
+
Float values of the raw speech waveform. Raw speech waveform can be
|
| 586 |
+
obtained by loading a `.flac` or `.wav` audio file into an array of type `list[float]`, a
|
| 587 |
+
`numpy.ndarray` or a `torch.Tensor`, *e.g.* via the torchcodec library (`pip install torchcodec`) or
|
| 588 |
+
the soundfile library (`pip install soundfile`). To prepare the array into
|
| 589 |
+
`input_features`, the [`AutoFeatureExtractor`] should be used for padding
|
| 590 |
+
and conversion into a tensor of type `torch.FloatTensor`.
|
| 591 |
+
decoder_position_ids (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`):
|
| 592 |
+
Indices of positions of each input sequence tokens in the position embeddings.
|
| 593 |
+
Used to calculate the position embeddings up to `config.decoder_config.max_position_embeddings`
|
| 594 |
+
|
| 595 |
+
Example:
|
| 596 |
+
|
| 597 |
+
```python
|
| 598 |
+
>>> import torch
|
| 599 |
+
>>> from transformers import AutoProcessor, CohereAsrForConditionalGeneration
|
| 600 |
+
>>> from datasets import load_dataset
|
| 601 |
+
|
| 602 |
+
>>> processor = AutoProcessor.from_pretrained("UsefulSensors/cohere_asr-tiny")
|
| 603 |
+
>>> model = CohereAsrForConditionalGeneration.from_pretrained("UsefulSensors/cohere_asr-tiny")
|
| 604 |
+
|
| 605 |
+
>>> ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
|
| 606 |
+
|
| 607 |
+
>>> inputs = processor(ds[0]["audio"]["array"], return_tensors="pt")
|
| 608 |
+
>>> input_features = inputs.input_features
|
| 609 |
+
|
| 610 |
+
>>> generated_ids = model.generate(input_features, max_new_tokens=100)
|
| 611 |
+
|
| 612 |
+
>>> transcription = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
|
| 613 |
+
>>> transcription
|
| 614 |
+
'Mr. Quilter is the apostle of the middle classes, and we are glad to welcome his gospel.'
|
| 615 |
+
```"""
|
| 616 |
+
# Main difference: uses `input_features` instead of `input_values`
|
| 617 |
+
if labels is not None:
|
| 618 |
+
if decoder_input_ids is None and decoder_inputs_embeds is None:
|
| 619 |
+
decoder_input_ids = shift_tokens_right(
|
| 620 |
+
labels, self.config.pad_token_id, self.config.decoder_start_token_id
|
| 621 |
+
)
|
| 622 |
+
|
| 623 |
+
outputs: Seq2SeqModelOutput = self.model(
|
| 624 |
+
input_features,
|
| 625 |
+
attention_mask=attention_mask,
|
| 626 |
+
decoder_input_ids=decoder_input_ids,
|
| 627 |
+
encoder_outputs=encoder_outputs,
|
| 628 |
+
decoder_attention_mask=decoder_attention_mask,
|
| 629 |
+
past_key_values=past_key_values,
|
| 630 |
+
decoder_inputs_embeds=decoder_inputs_embeds,
|
| 631 |
+
decoder_position_ids=decoder_position_ids,
|
| 632 |
+
use_cache=use_cache,
|
| 633 |
+
**kwargs,
|
| 634 |
+
)
|
| 635 |
+
logits = self.proj_out(outputs.last_hidden_state)
|
| 636 |
+
|
| 637 |
+
loss = None
|
| 638 |
+
if labels is not None:
|
| 639 |
+
loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size)
|
| 640 |
+
|
| 641 |
+
return Seq2SeqLMOutput(
|
| 642 |
+
loss=loss,
|
| 643 |
+
logits=logits,
|
| 644 |
+
past_key_values=outputs.past_key_values,
|
| 645 |
+
decoder_hidden_states=outputs.decoder_hidden_states,
|
| 646 |
+
decoder_attentions=outputs.decoder_attentions,
|
| 647 |
+
cross_attentions=outputs.cross_attentions,
|
| 648 |
+
encoder_last_hidden_state=outputs.encoder_last_hidden_state,
|
| 649 |
+
encoder_hidden_states=outputs.encoder_hidden_states,
|
| 650 |
+
encoder_attentions=outputs.encoder_attentions,
|
| 651 |
+
)
|
| 652 |
+
|
| 653 |
+
def prepare_inputs_for_generation(self, *args, audio_chunk_index=None, **kwargs):
|
| 654 |
+
# audio_chunk_index is returned by the processor but not used by the model, absorb it here
|
| 655 |
+
return super().prepare_inputs_for_generation(*args, **kwargs)
|
| 656 |
+
|
| 657 |
+
|
| 658 |
+
__all__ = ["CohereAsrPreTrainedModel", "CohereAsrModel", "CohereAsrForConditionalGeneration"]
|
third_party/transformers/src/transformers/models/cohere_asr/modular_cohere_asr.py
ADDED
|
@@ -0,0 +1,525 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 the HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from collections.abc import Callable
|
| 16 |
+
|
| 17 |
+
import torch
|
| 18 |
+
import torch.nn as nn
|
| 19 |
+
|
| 20 |
+
from ...cache_utils import Cache, DynamicCache, EncoderDecoderCache
|
| 21 |
+
from ...generation import GenerationMixin
|
| 22 |
+
from ...masking_utils import create_bidirectional_mask, create_causal_mask
|
| 23 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 24 |
+
from ...modeling_outputs import (
|
| 25 |
+
BaseModelOutput,
|
| 26 |
+
BaseModelOutputWithPastAndCrossAttentions,
|
| 27 |
+
Seq2SeqLMOutput,
|
| 28 |
+
Seq2SeqModelOutput,
|
| 29 |
+
)
|
| 30 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS
|
| 31 |
+
from ...processing_utils import Unpack
|
| 32 |
+
from ...utils import TransformersKwargs, auto_docstring
|
| 33 |
+
from ...utils.generic import can_return_tuple
|
| 34 |
+
from ...utils.output_capturing import OutputRecorder
|
| 35 |
+
from ..auto.modeling_auto import AutoModel
|
| 36 |
+
from ..clip.modeling_clip import CLIPMLP
|
| 37 |
+
from ..moonshine.modeling_moonshine import (
|
| 38 |
+
MoonshineDecoder,
|
| 39 |
+
MoonshineForConditionalGeneration,
|
| 40 |
+
MoonshineModel,
|
| 41 |
+
MoonshinePreTrainedModel,
|
| 42 |
+
eager_attention_forward,
|
| 43 |
+
shift_tokens_right,
|
| 44 |
+
)
|
| 45 |
+
from .configuration_cohere_asr import CohereAsrConfig
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class CohereAsrDecoderMLP(CLIPMLP):
|
| 49 |
+
pass
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
# Modular automatically inherits RoPE, hence no inheritance for now
|
| 53 |
+
class CohereAsrSelfAttention(nn.Module):
|
| 54 |
+
def __init__(self, config: CohereAsrConfig, layer_idx: int):
|
| 55 |
+
super().__init__()
|
| 56 |
+
self.config = config
|
| 57 |
+
self.layer_idx = layer_idx
|
| 58 |
+
self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
|
| 59 |
+
self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
|
| 60 |
+
self.scaling = self.head_dim**-0.5
|
| 61 |
+
self.attention_dropout = config.attention_dropout
|
| 62 |
+
self.is_causal = True
|
| 63 |
+
|
| 64 |
+
self.q_proj = nn.Linear(
|
| 65 |
+
config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
|
| 66 |
+
)
|
| 67 |
+
self.k_proj = nn.Linear(
|
| 68 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 69 |
+
)
|
| 70 |
+
self.v_proj = nn.Linear(
|
| 71 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 72 |
+
)
|
| 73 |
+
self.o_proj = nn.Linear(
|
| 74 |
+
config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
def forward(
|
| 78 |
+
self,
|
| 79 |
+
hidden_states: torch.Tensor,
|
| 80 |
+
attention_mask: torch.Tensor,
|
| 81 |
+
past_key_values: Cache | None = None,
|
| 82 |
+
**kwargs,
|
| 83 |
+
):
|
| 84 |
+
input_shape = hidden_states.shape[:-1]
|
| 85 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 86 |
+
|
| 87 |
+
query_states = self.q_proj(hidden_states)
|
| 88 |
+
key_states = self.k_proj(hidden_states)
|
| 89 |
+
value_states = self.v_proj(hidden_states)
|
| 90 |
+
|
| 91 |
+
query_states = query_states.view(hidden_shape).transpose(1, 2)
|
| 92 |
+
key_states = key_states.view(hidden_shape).transpose(1, 2)
|
| 93 |
+
value_states = value_states.view(hidden_shape).transpose(1, 2)
|
| 94 |
+
|
| 95 |
+
if past_key_values is not None:
|
| 96 |
+
past_key_values = past_key_values.self_attention_cache
|
| 97 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 98 |
+
|
| 99 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 100 |
+
self.config._attn_implementation, eager_attention_forward
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
attn_output, attn_weights = attention_interface(
|
| 104 |
+
self,
|
| 105 |
+
query_states,
|
| 106 |
+
key_states,
|
| 107 |
+
value_states,
|
| 108 |
+
attention_mask,
|
| 109 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 110 |
+
scaling=self.scaling,
|
| 111 |
+
**kwargs,
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 115 |
+
attn_output = self.o_proj(attn_output)
|
| 116 |
+
return attn_output, attn_weights
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
# Modular automatically inherits RoPE, hence no inheritance for now
|
| 120 |
+
class CohereAsrCrossAttention(nn.Module):
|
| 121 |
+
def __init__(self, config: CohereAsrConfig, layer_idx: int):
|
| 122 |
+
super().__init__()
|
| 123 |
+
self.config = config
|
| 124 |
+
self.layer_idx = layer_idx
|
| 125 |
+
self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
|
| 126 |
+
self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
|
| 127 |
+
self.scaling = self.head_dim**-0.5
|
| 128 |
+
self.attention_dropout = config.attention_dropout
|
| 129 |
+
self.is_causal = False
|
| 130 |
+
|
| 131 |
+
self.q_proj = nn.Linear(
|
| 132 |
+
config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
|
| 133 |
+
)
|
| 134 |
+
self.k_proj = nn.Linear(
|
| 135 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 136 |
+
)
|
| 137 |
+
self.v_proj = nn.Linear(
|
| 138 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 139 |
+
)
|
| 140 |
+
self.o_proj = nn.Linear(
|
| 141 |
+
config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
def forward(
|
| 145 |
+
self,
|
| 146 |
+
hidden_states: torch.Tensor,
|
| 147 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 148 |
+
attention_mask: torch.Tensor | None = None,
|
| 149 |
+
past_key_values: Cache | None = None,
|
| 150 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 151 |
+
):
|
| 152 |
+
# determine input shapes
|
| 153 |
+
bsz, tgt_len = hidden_states.shape[:-1]
|
| 154 |
+
src_len = encoder_hidden_states.shape[1]
|
| 155 |
+
|
| 156 |
+
q_input_shape = (bsz, tgt_len, -1, self.head_dim)
|
| 157 |
+
kv_input_shape = (bsz, src_len, -1, self.head_dim)
|
| 158 |
+
|
| 159 |
+
# get query proj
|
| 160 |
+
query_states = self.q_proj(hidden_states).view(*q_input_shape).transpose(1, 2)
|
| 161 |
+
|
| 162 |
+
is_updated = past_key_values.is_updated.get(self.layer_idx) if past_key_values is not None else False
|
| 163 |
+
if past_key_values is not None and is_updated:
|
| 164 |
+
# reuse k,v, cross_attentions
|
| 165 |
+
key_states = past_key_values.cross_attention_cache.layers[self.layer_idx].keys
|
| 166 |
+
value_states = past_key_values.cross_attention_cache.layers[self.layer_idx].values
|
| 167 |
+
else:
|
| 168 |
+
key_states = self.k_proj(encoder_hidden_states).view(*kv_input_shape).transpose(1, 2)
|
| 169 |
+
value_states = self.v_proj(encoder_hidden_states).view(*kv_input_shape).transpose(1, 2)
|
| 170 |
+
|
| 171 |
+
if past_key_values is not None:
|
| 172 |
+
# save all states to the cache
|
| 173 |
+
key_states, value_states = past_key_values.cross_attention_cache.update(
|
| 174 |
+
key_states, value_states, self.layer_idx
|
| 175 |
+
)
|
| 176 |
+
# set flag that curr layer for cross-attn is already updated so we can re-use in subsequent calls
|
| 177 |
+
past_key_values.is_updated[self.layer_idx] = True
|
| 178 |
+
|
| 179 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 180 |
+
self.config._attn_implementation, eager_attention_forward
|
| 181 |
+
)
|
| 182 |
+
|
| 183 |
+
attn_output, attn_weights = attention_interface(
|
| 184 |
+
self,
|
| 185 |
+
query_states,
|
| 186 |
+
key_states,
|
| 187 |
+
value_states,
|
| 188 |
+
attention_mask,
|
| 189 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 190 |
+
scaling=self.scaling,
|
| 191 |
+
**kwargs,
|
| 192 |
+
)
|
| 193 |
+
attn_output = attn_output.reshape(bsz, tgt_len, -1).contiguous()
|
| 194 |
+
attn_output = self.o_proj(attn_output)
|
| 195 |
+
return attn_output, attn_weights
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
class CohereAsrDecoderLayer(GradientCheckpointingLayer):
|
| 199 |
+
def __init__(self, config, layer_idx=None):
|
| 200 |
+
super().__init__()
|
| 201 |
+
self.self_attn = CohereAsrSelfAttention(config=config, layer_idx=layer_idx)
|
| 202 |
+
self.encoder_attn = CohereAsrCrossAttention(config=config, layer_idx=layer_idx)
|
| 203 |
+
|
| 204 |
+
self.mlp = CohereAsrDecoderMLP(config)
|
| 205 |
+
self.input_layernorm = nn.LayerNorm(config.hidden_size)
|
| 206 |
+
self.post_attention_layernorm = nn.LayerNorm(config.hidden_size)
|
| 207 |
+
self.final_layernorm = nn.LayerNorm(config.hidden_size)
|
| 208 |
+
|
| 209 |
+
def forward(
|
| 210 |
+
self,
|
| 211 |
+
hidden_states: torch.Tensor,
|
| 212 |
+
attention_mask: torch.Tensor | None = None,
|
| 213 |
+
encoder_hidden_states: torch.Tensor | None = None,
|
| 214 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 215 |
+
position_ids: torch.LongTensor | None = None,
|
| 216 |
+
encoder_position_ids: torch.LongTensor | None = None,
|
| 217 |
+
past_key_values: Cache | None = None,
|
| 218 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 219 |
+
) -> tuple[torch.FloatTensor, tuple[torch.FloatTensor, torch.FloatTensor] | None]:
|
| 220 |
+
residual = hidden_states
|
| 221 |
+
hidden_states = self.input_layernorm(hidden_states)
|
| 222 |
+
|
| 223 |
+
hidden_states, _ = self.self_attn(
|
| 224 |
+
hidden_states=hidden_states,
|
| 225 |
+
attention_mask=attention_mask,
|
| 226 |
+
position_ids=position_ids,
|
| 227 |
+
past_key_values=past_key_values,
|
| 228 |
+
**kwargs,
|
| 229 |
+
)
|
| 230 |
+
hidden_states = residual + hidden_states
|
| 231 |
+
|
| 232 |
+
if encoder_hidden_states is not None:
|
| 233 |
+
residual = hidden_states
|
| 234 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 235 |
+
hidden_states, _ = self.encoder_attn(
|
| 236 |
+
hidden_states=hidden_states,
|
| 237 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 238 |
+
attention_mask=encoder_attention_mask,
|
| 239 |
+
past_key_values=past_key_values,
|
| 240 |
+
)
|
| 241 |
+
hidden_states = residual + hidden_states
|
| 242 |
+
|
| 243 |
+
residual = hidden_states
|
| 244 |
+
hidden_states = self.final_layernorm(hidden_states)
|
| 245 |
+
hidden_states = self.mlp(hidden_states)
|
| 246 |
+
hidden_states = residual + hidden_states
|
| 247 |
+
return hidden_states
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
class CohereAsrPreTrainedModel(MoonshinePreTrainedModel):
|
| 251 |
+
main_input_name = "input_features"
|
| 252 |
+
_keys_to_ignore_on_load_unexpected = [r"preprocessor\.featurizer\..*"]
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
class CohereAsrDecoder(MoonshineDecoder):
|
| 256 |
+
_can_record_outputs = {
|
| 257 |
+
"attentions": OutputRecorder(CohereAsrSelfAttention, index=1, layer_name="self_attn"),
|
| 258 |
+
"hidden_states": CohereAsrDecoderLayer,
|
| 259 |
+
"cross_attentions": OutputRecorder(CohereAsrCrossAttention, index=1, layer_name="encoder_attn"),
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
def __init__(self, config):
|
| 263 |
+
super().__init__(config)
|
| 264 |
+
del self.rotary_emb
|
| 265 |
+
self.norm = nn.LayerNorm(config.hidden_size)
|
| 266 |
+
self.pos_emb = nn.Embedding(config.max_position_embeddings, config.hidden_size)
|
| 267 |
+
self.embedding_layernorm = nn.LayerNorm(config.hidden_size)
|
| 268 |
+
self.proj = nn.Linear(config.encoder_config.hidden_size, config.hidden_size, bias=True)
|
| 269 |
+
self.post_init()
|
| 270 |
+
|
| 271 |
+
def forward(
|
| 272 |
+
self,
|
| 273 |
+
input_ids: torch.LongTensor | None = None,
|
| 274 |
+
attention_mask: torch.Tensor | None = None,
|
| 275 |
+
position_ids: torch.LongTensor | None = None,
|
| 276 |
+
past_key_values: Cache | None = None,
|
| 277 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 278 |
+
use_cache: bool | None = None,
|
| 279 |
+
encoder_hidden_states: torch.FloatTensor | None = None,
|
| 280 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 281 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 282 |
+
) -> tuple | BaseModelOutputWithPastAndCrossAttentions:
|
| 283 |
+
r"""
|
| 284 |
+
encoder_hidden_states (`torch.FloatTensor` of shape `(batch_size, encoder_sequence_length, hidden_size)`, *optional*):
|
| 285 |
+
Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention
|
| 286 |
+
of the decoder.
|
| 287 |
+
encoder_attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 288 |
+
Mask to avoid performing attention on padding indices in `encoder_hidden_states`. Mask values selected in `[0, 1]`:
|
| 289 |
+
- 1 for tokens that are **not masked**,
|
| 290 |
+
- 0 for tokens that are **masked**.
|
| 291 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 292 |
+
"""
|
| 293 |
+
encoder_hidden_states = self.proj(encoder_hidden_states)
|
| 294 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 295 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 296 |
+
|
| 297 |
+
if inputs_embeds is None:
|
| 298 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 299 |
+
|
| 300 |
+
if use_cache and past_key_values is None:
|
| 301 |
+
past_key_values = EncoderDecoderCache(DynamicCache(config=self.config), DynamicCache(config=self.config))
|
| 302 |
+
|
| 303 |
+
if position_ids is None:
|
| 304 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 305 |
+
position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
|
| 306 |
+
position_ids = position_ids.unsqueeze(0)
|
| 307 |
+
|
| 308 |
+
# Fixed sinusoidal position embedding added to token embeddings, then layernorm
|
| 309 |
+
pos_emb = self.pos_emb(position_ids.squeeze(0))
|
| 310 |
+
inputs_embeds = self.embedding_layernorm(inputs_embeds + pos_emb)
|
| 311 |
+
|
| 312 |
+
causal_mask = create_causal_mask(
|
| 313 |
+
config=self.config,
|
| 314 |
+
inputs_embeds=inputs_embeds,
|
| 315 |
+
attention_mask=attention_mask,
|
| 316 |
+
past_key_values=past_key_values,
|
| 317 |
+
position_ids=position_ids,
|
| 318 |
+
)
|
| 319 |
+
encoder_attention_mask = create_bidirectional_mask(
|
| 320 |
+
config=self.config,
|
| 321 |
+
inputs_embeds=inputs_embeds,
|
| 322 |
+
attention_mask=encoder_attention_mask,
|
| 323 |
+
encoder_hidden_states=encoder_hidden_states,
|
| 324 |
+
)
|
| 325 |
+
|
| 326 |
+
hidden_states = inputs_embeds
|
| 327 |
+
for decoder_layer in self.layers:
|
| 328 |
+
hidden_states = decoder_layer(
|
| 329 |
+
hidden_states,
|
| 330 |
+
causal_mask,
|
| 331 |
+
encoder_hidden_states, # as a positional argument for gradient checkpointing
|
| 332 |
+
encoder_attention_mask=encoder_attention_mask,
|
| 333 |
+
position_ids=position_ids,
|
| 334 |
+
past_key_values=past_key_values,
|
| 335 |
+
**kwargs,
|
| 336 |
+
)
|
| 337 |
+
|
| 338 |
+
hidden_states = self.norm(hidden_states)
|
| 339 |
+
|
| 340 |
+
return BaseModelOutputWithPastAndCrossAttentions(
|
| 341 |
+
last_hidden_state=hidden_states,
|
| 342 |
+
past_key_values=past_key_values if use_cache else None,
|
| 343 |
+
)
|
| 344 |
+
|
| 345 |
+
|
| 346 |
+
class CohereAsrModel(MoonshineModel):
|
| 347 |
+
def __init__(self, config):
|
| 348 |
+
super().__init__(config)
|
| 349 |
+
self.encoder = AutoModel.from_config(config.encoder_config)
|
| 350 |
+
|
| 351 |
+
@can_return_tuple
|
| 352 |
+
@auto_docstring
|
| 353 |
+
def forward(
|
| 354 |
+
self,
|
| 355 |
+
input_features: torch.FloatTensor | None = None,
|
| 356 |
+
attention_mask: torch.LongTensor | None = None,
|
| 357 |
+
decoder_input_ids: torch.LongTensor | None = None,
|
| 358 |
+
decoder_attention_mask: torch.LongTensor | None = None,
|
| 359 |
+
encoder_outputs: tuple[tuple[torch.FloatTensor]] | None = None,
|
| 360 |
+
past_key_values: EncoderDecoderCache | None = None,
|
| 361 |
+
decoder_inputs_embeds: tuple[torch.FloatTensor] | None = None,
|
| 362 |
+
decoder_position_ids: tuple[torch.LongTensor] | None = None,
|
| 363 |
+
use_cache: bool | None = None,
|
| 364 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 365 |
+
) -> Seq2SeqModelOutput:
|
| 366 |
+
r"""
|
| 367 |
+
input_features (`torch.FloatTensor` of shape `(batch_size, audio_length)`):
|
| 368 |
+
Float values of the raw speech waveform. Raw speech waveform can be
|
| 369 |
+
obtained by loading a `.flac` or `.wav` audio file into an array of type `list[float]`, a
|
| 370 |
+
`numpy.ndarray` or a `torch.Tensor`, *e.g.* via the torchcodec library (`pip install torchcodec`) or
|
| 371 |
+
the soundfile library (`pip install soundfile`). To prepare the array into
|
| 372 |
+
`input_features`, the [`AutoFeatureExtractor`] should be used for padding
|
| 373 |
+
and conversion into a tensor of type `torch.FloatTensor`.
|
| 374 |
+
decoder_position_ids (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`):
|
| 375 |
+
Indices of positions of each input sequence tokens in the position embeddings.
|
| 376 |
+
Used to calculate the position embeddings up to `config.decoder_config.max_position_embeddings`
|
| 377 |
+
|
| 378 |
+
Example:
|
| 379 |
+
|
| 380 |
+
```python
|
| 381 |
+
>>> import torch
|
| 382 |
+
>>> from transformers import AutoFeatureExtractor, CohereAsrModel
|
| 383 |
+
>>> from datasets import load_dataset
|
| 384 |
+
|
| 385 |
+
>>> model = CohereAsrModel.from_pretrained("UsefulSensors/cohere_asr-tiny")
|
| 386 |
+
>>> feature_extractor = AutoFeatureExtractor.from_pretrained("UsefulSensors/cohere_asr-tiny")
|
| 387 |
+
>>> ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
|
| 388 |
+
>>> inputs = feature_extractor(ds[0]["audio"]["array"], return_tensors="pt")
|
| 389 |
+
>>> input_features = inputs.input_features
|
| 390 |
+
>>> decoder_input_ids = torch.tensor([[1, 1]]) * model.config.decoder_start_token_id
|
| 391 |
+
>>> last_hidden_state = model(input_features, decoder_input_ids=decoder_input_ids).last_hidden_state
|
| 392 |
+
>>> list(last_hidden_state.shape)
|
| 393 |
+
[1, 2, 288]
|
| 394 |
+
```
|
| 395 |
+
"""
|
| 396 |
+
# Main difference: uses `input_features` instead of `input_values`
|
| 397 |
+
if encoder_outputs is None:
|
| 398 |
+
encoder_outputs: BaseModelOutput = self.encoder(input_features, attention_mask=attention_mask, **kwargs)
|
| 399 |
+
|
| 400 |
+
decoder_outputs: BaseModelOutputWithPastAndCrossAttentions = self.decoder(
|
| 401 |
+
input_ids=decoder_input_ids,
|
| 402 |
+
attention_mask=decoder_attention_mask,
|
| 403 |
+
encoder_hidden_states=encoder_outputs.last_hidden_state,
|
| 404 |
+
encoder_attention_mask=encoder_outputs.attention_mask,
|
| 405 |
+
past_key_values=past_key_values,
|
| 406 |
+
inputs_embeds=decoder_inputs_embeds,
|
| 407 |
+
position_ids=decoder_position_ids,
|
| 408 |
+
use_cache=use_cache,
|
| 409 |
+
**kwargs,
|
| 410 |
+
)
|
| 411 |
+
|
| 412 |
+
return Seq2SeqModelOutput(
|
| 413 |
+
last_hidden_state=decoder_outputs.last_hidden_state,
|
| 414 |
+
past_key_values=decoder_outputs.past_key_values,
|
| 415 |
+
decoder_hidden_states=decoder_outputs.hidden_states,
|
| 416 |
+
decoder_attentions=decoder_outputs.attentions,
|
| 417 |
+
cross_attentions=decoder_outputs.cross_attentions,
|
| 418 |
+
encoder_last_hidden_state=encoder_outputs.last_hidden_state,
|
| 419 |
+
encoder_hidden_states=encoder_outputs.hidden_states,
|
| 420 |
+
encoder_attentions=encoder_outputs.attentions,
|
| 421 |
+
)
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
class CohereAsrForConditionalGeneration(MoonshineForConditionalGeneration):
|
| 425 |
+
def __init__(self, config):
|
| 426 |
+
super().__init__(config)
|
| 427 |
+
self.proj_out = nn.Linear(config.hidden_size, config.vocab_size, bias=True)
|
| 428 |
+
self.post_init()
|
| 429 |
+
|
| 430 |
+
@can_return_tuple
|
| 431 |
+
@auto_docstring
|
| 432 |
+
def forward(
|
| 433 |
+
self,
|
| 434 |
+
input_features: torch.FloatTensor | None = None,
|
| 435 |
+
attention_mask: torch.LongTensor | None = None,
|
| 436 |
+
decoder_input_ids: torch.LongTensor | None = None,
|
| 437 |
+
decoder_attention_mask: torch.LongTensor | None = None,
|
| 438 |
+
encoder_outputs: tuple[tuple[torch.FloatTensor]] | None = None,
|
| 439 |
+
past_key_values: EncoderDecoderCache | None = None,
|
| 440 |
+
decoder_inputs_embeds: tuple[torch.FloatTensor] | None = None,
|
| 441 |
+
decoder_position_ids: tuple[torch.LongTensor] | None = None,
|
| 442 |
+
use_cache: bool | None = None,
|
| 443 |
+
labels: torch.LongTensor | None = None,
|
| 444 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 445 |
+
) -> Seq2SeqLMOutput:
|
| 446 |
+
r"""
|
| 447 |
+
input_features (`torch.FloatTensor` of shape `(batch_size, audio_length)`):
|
| 448 |
+
Float values of the raw speech waveform. Raw speech waveform can be
|
| 449 |
+
obtained by loading a `.flac` or `.wav` audio file into an array of type `list[float]`, a
|
| 450 |
+
`numpy.ndarray` or a `torch.Tensor`, *e.g.* via the torchcodec library (`pip install torchcodec`) or
|
| 451 |
+
the soundfile library (`pip install soundfile`). To prepare the array into
|
| 452 |
+
`input_features`, the [`AutoFeatureExtractor`] should be used for padding
|
| 453 |
+
and conversion into a tensor of type `torch.FloatTensor`.
|
| 454 |
+
decoder_position_ids (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`):
|
| 455 |
+
Indices of positions of each input sequence tokens in the position embeddings.
|
| 456 |
+
Used to calculate the position embeddings up to `config.decoder_config.max_position_embeddings`
|
| 457 |
+
|
| 458 |
+
Example:
|
| 459 |
+
|
| 460 |
+
```python
|
| 461 |
+
>>> import torch
|
| 462 |
+
>>> from transformers import AutoProcessor, CohereAsrForConditionalGeneration
|
| 463 |
+
>>> from datasets import load_dataset
|
| 464 |
+
|
| 465 |
+
>>> processor = AutoProcessor.from_pretrained("UsefulSensors/cohere_asr-tiny")
|
| 466 |
+
>>> model = CohereAsrForConditionalGeneration.from_pretrained("UsefulSensors/cohere_asr-tiny")
|
| 467 |
+
|
| 468 |
+
>>> ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
|
| 469 |
+
|
| 470 |
+
>>> inputs = processor(ds[0]["audio"]["array"], return_tensors="pt")
|
| 471 |
+
>>> input_features = inputs.input_features
|
| 472 |
+
|
| 473 |
+
>>> generated_ids = model.generate(input_features, max_new_tokens=100)
|
| 474 |
+
|
| 475 |
+
>>> transcription = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
|
| 476 |
+
>>> transcription
|
| 477 |
+
'Mr. Quilter is the apostle of the middle classes, and we are glad to welcome his gospel.'
|
| 478 |
+
```"""
|
| 479 |
+
# Main difference: uses `input_features` instead of `input_values`
|
| 480 |
+
if labels is not None:
|
| 481 |
+
if decoder_input_ids is None and decoder_inputs_embeds is None:
|
| 482 |
+
decoder_input_ids = shift_tokens_right(
|
| 483 |
+
labels, self.config.pad_token_id, self.config.decoder_start_token_id
|
| 484 |
+
)
|
| 485 |
+
|
| 486 |
+
outputs: Seq2SeqModelOutput = self.model(
|
| 487 |
+
input_features,
|
| 488 |
+
attention_mask=attention_mask,
|
| 489 |
+
decoder_input_ids=decoder_input_ids,
|
| 490 |
+
encoder_outputs=encoder_outputs,
|
| 491 |
+
decoder_attention_mask=decoder_attention_mask,
|
| 492 |
+
past_key_values=past_key_values,
|
| 493 |
+
decoder_inputs_embeds=decoder_inputs_embeds,
|
| 494 |
+
decoder_position_ids=decoder_position_ids,
|
| 495 |
+
use_cache=use_cache,
|
| 496 |
+
**kwargs,
|
| 497 |
+
)
|
| 498 |
+
logits = self.proj_out(outputs.last_hidden_state)
|
| 499 |
+
|
| 500 |
+
loss = None
|
| 501 |
+
if labels is not None:
|
| 502 |
+
loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size)
|
| 503 |
+
|
| 504 |
+
return Seq2SeqLMOutput(
|
| 505 |
+
loss=loss,
|
| 506 |
+
logits=logits,
|
| 507 |
+
past_key_values=outputs.past_key_values,
|
| 508 |
+
decoder_hidden_states=outputs.decoder_hidden_states,
|
| 509 |
+
decoder_attentions=outputs.decoder_attentions,
|
| 510 |
+
cross_attentions=outputs.cross_attentions,
|
| 511 |
+
encoder_last_hidden_state=outputs.encoder_last_hidden_state,
|
| 512 |
+
encoder_hidden_states=outputs.encoder_hidden_states,
|
| 513 |
+
encoder_attentions=outputs.encoder_attentions,
|
| 514 |
+
)
|
| 515 |
+
|
| 516 |
+
def prepare_inputs_for_generation(self, *args, audio_chunk_index=None, **kwargs):
|
| 517 |
+
# audio_chunk_index is returned by the processor but not used by the model, absorb it here
|
| 518 |
+
return GenerationMixin.prepare_inputs_for_generation(self, *args, **kwargs)
|
| 519 |
+
|
| 520 |
+
|
| 521 |
+
__all__ = [
|
| 522 |
+
"CohereAsrPreTrainedModel",
|
| 523 |
+
"CohereAsrModel",
|
| 524 |
+
"CohereAsrForConditionalGeneration",
|
| 525 |
+
]
|
third_party/transformers/src/transformers/models/cohere_asr/processing_cohere_asr.py
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from ...audio_utils import AudioInput, make_list_of_audio
|
| 16 |
+
from ...processing_utils import ProcessingKwargs, ProcessorMixin, Unpack
|
| 17 |
+
from ...tokenization_utils_base import PreTokenizedInput, TextInput
|
| 18 |
+
from ...utils import auto_docstring, is_torch_available, logging
|
| 19 |
+
from ...utils.import_utils import requires
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
if is_torch_available():
|
| 23 |
+
import torch
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
LANGUAGES = {"ar", "de", "el", "en", "es", "fr", "it", "ja", "ko", "nl", "pl", "pt", "vi", "zh"}
|
| 27 |
+
_NO_SPACE_LANGS = {"ja", "zh"}
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
logger = logging.get_logger(__name__)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
class CohereAsrProcessorKwargs(ProcessingKwargs, total=False):
|
| 34 |
+
_defaults = {
|
| 35 |
+
"audio_kwargs": {
|
| 36 |
+
"sampling_rate": 16000,
|
| 37 |
+
"padding": "longest",
|
| 38 |
+
"return_attention_mask": True,
|
| 39 |
+
},
|
| 40 |
+
"text_kwargs": {
|
| 41 |
+
"padding": True,
|
| 42 |
+
"padding_side": "right",
|
| 43 |
+
"add_special_tokens": False,
|
| 44 |
+
},
|
| 45 |
+
"common_kwargs": {"return_tensors": "pt"},
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
@auto_docstring
|
| 50 |
+
@requires(backends=("torch",))
|
| 51 |
+
class CohereAsrProcessor(ProcessorMixin):
|
| 52 |
+
def __init__(self, feature_extractor, tokenizer):
|
| 53 |
+
super().__init__(feature_extractor, tokenizer)
|
| 54 |
+
|
| 55 |
+
def get_decoder_prompt_ids(self, language: str, punctuation: bool = True) -> list[int]:
|
| 56 |
+
"""Build the decoder prompt token IDs for the given language and punctuation settings."""
|
| 57 |
+
if language not in LANGUAGES:
|
| 58 |
+
raise ValueError(
|
| 59 |
+
f"Unsupported language: {language!r}. Supported languages: {', '.join(sorted(LANGUAGES))}."
|
| 60 |
+
)
|
| 61 |
+
pnc_token = "<|pnc|>" if punctuation else "<|nopnc|>"
|
| 62 |
+
tokens = [
|
| 63 |
+
"▁",
|
| 64 |
+
"<|startofcontext|>",
|
| 65 |
+
"<|startoftranscript|>",
|
| 66 |
+
"<|emo:undefined|>",
|
| 67 |
+
f"<|{language}|>",
|
| 68 |
+
f"<|{language}|>",
|
| 69 |
+
pnc_token,
|
| 70 |
+
"<|noitn|>",
|
| 71 |
+
"<|notimestamp|>",
|
| 72 |
+
"<|nodiarize|>",
|
| 73 |
+
]
|
| 74 |
+
return self.tokenizer.convert_tokens_to_ids(tokens)
|
| 75 |
+
|
| 76 |
+
@auto_docstring
|
| 77 |
+
def __call__(
|
| 78 |
+
self,
|
| 79 |
+
audio: AudioInput,
|
| 80 |
+
language: str,
|
| 81 |
+
text: TextInput | PreTokenizedInput | list[TextInput] | list[PreTokenizedInput] | None = None,
|
| 82 |
+
punctuation: bool = True,
|
| 83 |
+
sampling_rate: int | None = None,
|
| 84 |
+
**kwargs: Unpack[CohereAsrProcessorKwargs],
|
| 85 |
+
):
|
| 86 |
+
r"""
|
| 87 |
+
language (`str`):
|
| 88 |
+
Language code (e.g. `"en"`, `"es"`, `"fr"`) used to build the decoder prompt. The processor
|
| 89 |
+
constructs the full decoder prompt and returns `decoder_input_ids` alongside the audio features.
|
| 90 |
+
punctuation (`bool`, defaults to `True`):
|
| 91 |
+
Whether to enable punctuation in the decoder prompt.
|
| 92 |
+
sampling_rate (`int`, *optional*):
|
| 93 |
+
The sampling rate of the input audio in Hz. This should match the sampling rate expected by the feature
|
| 94 |
+
extractor (defaults to 16000 Hz). If provided, it will be validated against the processor's expected
|
| 95 |
+
sampling rate, and an error will be raised if they don't match. If not provided, a warning will be
|
| 96 |
+
issued and the default sampling rate will be assumed.
|
| 97 |
+
"""
|
| 98 |
+
audio = make_list_of_audio(audio)
|
| 99 |
+
|
| 100 |
+
output_kwargs = self._merge_kwargs(
|
| 101 |
+
CohereAsrProcessorKwargs,
|
| 102 |
+
tokenizer_init_kwargs=self.tokenizer.init_kwargs,
|
| 103 |
+
**kwargs,
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
if sampling_rate is None:
|
| 107 |
+
logger.warning_once(
|
| 108 |
+
f"You've provided audio without specifying the sampling rate. It will be assumed to be {output_kwargs['audio_kwargs']['sampling_rate']}, which can result in silent errors."
|
| 109 |
+
)
|
| 110 |
+
elif sampling_rate != output_kwargs["audio_kwargs"]["sampling_rate"]:
|
| 111 |
+
raise ValueError(
|
| 112 |
+
f"The sampling rate of the audio ({sampling_rate}) does not match the sampling rate of the processor ({output_kwargs['audio_kwargs']['sampling_rate']}). Please provide resampled the audio to the expected sampling rate."
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
inputs = self.feature_extractor(audio, **output_kwargs["audio_kwargs"])
|
| 116 |
+
|
| 117 |
+
prompt_ids = self.get_decoder_prompt_ids(language=language, punctuation=punctuation)
|
| 118 |
+
batch_size = inputs["input_features"].shape[0]
|
| 119 |
+
inputs["decoder_input_ids"] = torch.tensor([prompt_ids] * batch_size, dtype=torch.long)
|
| 120 |
+
|
| 121 |
+
if text is not None:
|
| 122 |
+
encodings = self.tokenizer(text, **output_kwargs["text_kwargs"])
|
| 123 |
+
inputs["labels"] = encodings["input_ids"]
|
| 124 |
+
|
| 125 |
+
return inputs
|
| 126 |
+
|
| 127 |
+
def decode(self, *args, audio_chunk_index=None, language=None, **kwargs):
|
| 128 |
+
texts = self.tokenizer.decode(*args, **kwargs)
|
| 129 |
+
if audio_chunk_index is None:
|
| 130 |
+
return texts
|
| 131 |
+
if language is None:
|
| 132 |
+
raise ValueError("`language` must be provided when `audio_chunk_index` is given.")
|
| 133 |
+
separator = "" if language in _NO_SPACE_LANGS else " "
|
| 134 |
+
return self._reassemble_chunk_texts(texts, audio_chunk_index, separator)
|
| 135 |
+
|
| 136 |
+
@staticmethod
|
| 137 |
+
def _reassemble_chunk_texts(
|
| 138 |
+
texts: list[str],
|
| 139 |
+
audio_chunk_index: list[tuple[int, int | None]],
|
| 140 |
+
separator: str = " ",
|
| 141 |
+
) -> list[str]:
|
| 142 |
+
"""Reassemble per-chunk transcription texts back into per-sample strings.
|
| 143 |
+
|
| 144 |
+
When audio inputs are longer than the feature extractor's `max_audio_clip_s`, they are split into
|
| 145 |
+
overlapping chunks before being fed to the model. This means a single original audio sample can
|
| 146 |
+
produce multiple decoded text segments. This method reverses that chunking: it groups the decoded
|
| 147 |
+
texts by their original sample index using `chunk_map`, orders the chunks, and joins them
|
| 148 |
+
with `separator` to reconstruct one transcription string per input sample.
|
| 149 |
+
|
| 150 |
+
Args:
|
| 151 |
+
texts: Decoded text strings, one per model output (i.e. one per chunk).
|
| 152 |
+
audio_chunk_index: List of `(sample_idx, chunk_idx)` tuples that map each entry in
|
| 153 |
+
`texts` back to its original sample and chunk position. A `chunk_idx` of `None`
|
| 154 |
+
indicates the sample was not chunked.
|
| 155 |
+
separator: String used to join chunks belonging to the same sample. Defaults to a
|
| 156 |
+
space; callers pass an empty string for languages that don't use spaces between
|
| 157 |
+
words (e.g. Chinese, Japanese).
|
| 158 |
+
|
| 159 |
+
Returns:
|
| 160 |
+
A list of reassembled transcription strings, one per original input sample.
|
| 161 |
+
"""
|
| 162 |
+
max_sample_idx = max(sample_idx for sample_idx, _ in audio_chunk_index)
|
| 163 |
+
outputs = [""] * (max_sample_idx + 1)
|
| 164 |
+
chunked = {}
|
| 165 |
+
|
| 166 |
+
for (sample_idx, chunk_idx), text in zip(audio_chunk_index, texts):
|
| 167 |
+
if chunk_idx is None:
|
| 168 |
+
outputs[sample_idx] = text
|
| 169 |
+
else:
|
| 170 |
+
if sample_idx not in chunked:
|
| 171 |
+
chunked[sample_idx] = []
|
| 172 |
+
chunked[sample_idx].append((chunk_idx, text))
|
| 173 |
+
|
| 174 |
+
for sample_idx, chunk_items in chunked.items():
|
| 175 |
+
chunk_items.sort(key=lambda item: item[0])
|
| 176 |
+
non_empty = [t for _, t in chunk_items if t and t.strip()]
|
| 177 |
+
parts = [non_empty[0].rstrip()] + [t.strip() for t in non_empty[1:]]
|
| 178 |
+
outputs[sample_idx] = separator.join(parts)
|
| 179 |
+
|
| 180 |
+
return outputs
|
| 181 |
+
|
| 182 |
+
@property
|
| 183 |
+
def model_input_names(self):
|
| 184 |
+
feature_extractor_input_names = self.feature_extractor.model_input_names
|
| 185 |
+
return feature_extractor_input_names + ["labels"]
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
__all__ = ["CohereAsrProcessor"]
|
third_party/transformers/src/transformers/models/deepseek_vl_hybrid/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 Deepseek AI and The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
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_deepseek_vl_hybrid import *
|
| 22 |
+
from .image_processing_deepseek_vl_hybrid import *
|
| 23 |
+
from .image_processing_pil_deepseek_vl_hybrid import *
|
| 24 |
+
from .modeling_deepseek_vl_hybrid import *
|
| 25 |
+
from .processing_deepseek_vl_hybrid import *
|
| 26 |
+
else:
|
| 27 |
+
import sys
|
| 28 |
+
|
| 29 |
+
_file = globals()["__file__"]
|
| 30 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/deepseek_vl_hybrid/configuration_deepseek_vl_hybrid.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.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_deepseek_vl_hybrid.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 Deepseek AI and The HuggingFace Team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from huggingface_hub.dataclasses import strict
|
| 22 |
+
|
| 23 |
+
from ...configuration_utils import PreTrainedConfig
|
| 24 |
+
from ...utils import auto_docstring, logging
|
| 25 |
+
from ..auto import CONFIG_MAPPING, AutoConfig
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
logger = logging.get_logger(__name__)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
@auto_docstring(checkpoint="deepseek-community/deepseek-vl-7b-chat")
|
| 32 |
+
@strict
|
| 33 |
+
class DeepseekVLHybridConfig(PreTrainedConfig):
|
| 34 |
+
r"""
|
| 35 |
+
high_res_vision_config (`Union[AutoConfig, dict]`, *optional*, defaults to `SamVisionConfig`):
|
| 36 |
+
The config object or dictionary of the high resolution vision backbone.
|
| 37 |
+
|
| 38 |
+
Example:
|
| 39 |
+
|
| 40 |
+
```python
|
| 41 |
+
>>> from transformers import DeepseekVLHybridConfig, DeepseekVLHybridModel
|
| 42 |
+
|
| 43 |
+
>>> # Initializing a DeepseekVLHybrid deepseek-community/deepseek-vl-7b-chat style configuration
|
| 44 |
+
>>> configuration = DeepseekVLHybridConfig()
|
| 45 |
+
|
| 46 |
+
>>> # Initializing a model (with random weights) from the deepseek-community/deepseek-vl-7b-chat style configuration
|
| 47 |
+
>>> model = DeepseekVLHybridModel(configuration)
|
| 48 |
+
|
| 49 |
+
>>> # Accessing the model configuration
|
| 50 |
+
>>> configuration = model.config
|
| 51 |
+
```"""
|
| 52 |
+
|
| 53 |
+
model_type = "deepseek_vl_hybrid"
|
| 54 |
+
sub_configs = {"text_config": AutoConfig, "vision_config": AutoConfig, "high_res_vision_config": AutoConfig}
|
| 55 |
+
|
| 56 |
+
text_config: dict | PreTrainedConfig | None = None
|
| 57 |
+
vision_config: dict | PreTrainedConfig | None = None
|
| 58 |
+
image_token_id: int = 100015
|
| 59 |
+
tie_word_embeddings: bool = True
|
| 60 |
+
|
| 61 |
+
high_res_vision_config: dict | PreTrainedConfig | None = None
|
| 62 |
+
|
| 63 |
+
def __post_init__(self, **kwargs):
|
| 64 |
+
if self.high_res_vision_config is None:
|
| 65 |
+
self.high_res_vision_config = {}
|
| 66 |
+
logger.info("`high_res_vision_config` is `None`. Initializing the `SamVisionConfig` with default values.")
|
| 67 |
+
|
| 68 |
+
if isinstance(self.high_res_vision_config, dict):
|
| 69 |
+
self.high_res_vision_config["model_type"] = self.high_res_vision_config.get(
|
| 70 |
+
"model_type", "sam_vision_model"
|
| 71 |
+
)
|
| 72 |
+
self.high_res_vision_config = CONFIG_MAPPING[self.high_res_vision_config["model_type"]](
|
| 73 |
+
**self.high_res_vision_config
|
| 74 |
+
)
|
| 75 |
+
if self.text_config is None:
|
| 76 |
+
self.text_config = {}
|
| 77 |
+
logger.info("`text_config` is `None`. Initializing the `LlamaConfig` with default values.")
|
| 78 |
+
if isinstance(self.text_config, dict):
|
| 79 |
+
self.text_config["model_type"] = self.text_config.get("model_type", "llama")
|
| 80 |
+
self.text_config = CONFIG_MAPPING[self.text_config["model_type"]](**self.text_config)
|
| 81 |
+
|
| 82 |
+
if self.vision_config is None:
|
| 83 |
+
self.vision_config = {}
|
| 84 |
+
logger.info("`vision_config` is `None`. Initializing the `SiglipVisionConfig` with default values.")
|
| 85 |
+
if isinstance(self.vision_config, dict):
|
| 86 |
+
self.vision_config["model_type"] = self.vision_config.get("model_type", "siglip_vision_model")
|
| 87 |
+
self.vision_config = CONFIG_MAPPING[self.vision_config["model_type"]](**self.vision_config)
|
| 88 |
+
|
| 89 |
+
super().__post_init__(**kwargs)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
__all__ = ["DeepseekVLHybridConfig"]
|
third_party/transformers/src/transformers/models/deepseek_vl_hybrid/convert_deepseek_vl_hybrid_weights_to_hf.py
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 Deepseek AI and The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
import argparse
|
| 15 |
+
import gc
|
| 16 |
+
import json
|
| 17 |
+
import os
|
| 18 |
+
|
| 19 |
+
import regex as re
|
| 20 |
+
import torch
|
| 21 |
+
from huggingface_hub import snapshot_download
|
| 22 |
+
from huggingface_hub.errors import HFValidationError
|
| 23 |
+
from safetensors.torch import load_file
|
| 24 |
+
|
| 25 |
+
from transformers import (
|
| 26 |
+
AutoTokenizer,
|
| 27 |
+
DeepseekVLHybridConfig,
|
| 28 |
+
DeepseekVLHybridForConditionalGeneration,
|
| 29 |
+
DeepseekVLHybridImageProcessor,
|
| 30 |
+
DeepseekVLHybridProcessor,
|
| 31 |
+
)
|
| 32 |
+
from transformers.image_utils import (
|
| 33 |
+
IMAGENET_STANDARD_MEAN,
|
| 34 |
+
IMAGENET_STANDARD_STD,
|
| 35 |
+
OPENAI_CLIP_MEAN,
|
| 36 |
+
OPENAI_CLIP_STD,
|
| 37 |
+
PILImageResampling,
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
# fmt: off
|
| 42 |
+
ORIGINAL_TO_CONVERTED_KEY_MAPPING = {
|
| 43 |
+
# # Sam (High Resolution)
|
| 44 |
+
r"vision_model.vision_tower_high.vision_tower.pos_embed": r"model.high_res_vision_model.vision_encoder.pos_embed",
|
| 45 |
+
r"vision_model.vision_tower_high.vision_tower.patch_embed.proj.(weight|bias)": r"model.high_res_vision_model.vision_encoder.patch_embed.projection.\1",
|
| 46 |
+
r"vision_model.vision_tower_high.vision_tower.blocks.(\d+).norm(\d+).(weight|bias)": r"model.high_res_vision_model.vision_encoder.layers.\1.layer_norm\2.\3",
|
| 47 |
+
r"vision_model.vision_tower_high.vision_tower.blocks.(\d+).attn.rel_pos_(h|w)": r"model.high_res_vision_model.vision_encoder.layers.\1.attn.rel_pos_\2",
|
| 48 |
+
r"vision_model.vision_tower_high.vision_tower.blocks.(\d+).attn.qkv.(weight|bias)": r"model.high_res_vision_model.vision_encoder.layers.\1.attn.qkv.\2",
|
| 49 |
+
r"vision_model.vision_tower_high.vision_tower.blocks.(\d+).attn.proj.(weight|bias)": r"model.high_res_vision_model.vision_encoder.layers.\1.attn.proj.\2",
|
| 50 |
+
r"vision_model.vision_tower_high.vision_tower.blocks.(\d+).mlp.lin(\d+).(weight|bias)": r"model.high_res_vision_model.vision_encoder.layers.\1.mlp.lin\2.\3",
|
| 51 |
+
r"vision_model.vision_tower_high.vision_tower.neck.0.weight": r"model.high_res_vision_model.vision_encoder.neck.conv1.weight",
|
| 52 |
+
r"vision_model.vision_tower_high.vision_tower.neck.1.(weight|bias)": r"model.high_res_vision_model.vision_encoder.neck.layer_norm1.\1",
|
| 53 |
+
r"vision_model.vision_tower_high.vision_tower.neck.2.weight": r"model.high_res_vision_model.vision_encoder.neck.conv2.weight",
|
| 54 |
+
r"vision_model.vision_tower_high.vision_tower.neck.3.(weight|bias)": r"model.high_res_vision_model.vision_encoder.neck.layer_norm2.\1",
|
| 55 |
+
r"vision_model.vision_tower_high.vision_tower.neck_hd.0.weight": r"model.high_res_vision_neck.conv1.weight",
|
| 56 |
+
r"vision_model.vision_tower_high.vision_tower.neck_hd.1.(weight|bias)": r"model.high_res_vision_neck.layer_norm1.\1",
|
| 57 |
+
r"vision_model.vision_tower_high.vision_tower.neck_hd.2.weight": r"model.high_res_vision_neck.conv2.weight",
|
| 58 |
+
r"vision_model.vision_tower_high.vision_tower.neck_hd.3.(weight|bias)": r"model.high_res_vision_neck.layer_norm2.\1",
|
| 59 |
+
r"vision_model.vision_tower_high.vision_tower.downsamples.0.weight": r"model.high_res_vision_proj.conv1.weight",
|
| 60 |
+
r"vision_model.vision_tower_high.vision_tower.downsamples.1.weight": r"model.high_res_vision_proj.conv2.weight",
|
| 61 |
+
r"vision_model.vision_tower_high.vision_tower.hd_alpha_downsamples": r"model.high_res_vision_alpha",
|
| 62 |
+
|
| 63 |
+
# Siglip (Low Resolution)
|
| 64 |
+
r"vision_model.vision_tower_low.vision_tower.pos_embed": r"model.vision_model.vision_model.embeddings.position_embedding.weight",
|
| 65 |
+
r"vision_model.vision_tower_low.vision_tower.patch_embed.proj.(weight|bias)": r"model.vision_model.vision_model.embeddings.patch_embedding.\1",
|
| 66 |
+
r"vision_model.vision_tower_low.vision_tower.blocks.(\d+).attn.qkv.(weight|bias)": r"model.vision_model.vision_model.encoder.layers.\1.self_attn.(q|k|v)_proj.\2",
|
| 67 |
+
r"vision_model.vision_tower_low.vision_tower.blocks.(\d+).attn.proj.(weight|bias)": r"model.vision_model.vision_model.encoder.layers.\1.self_attn.out_proj.\2",
|
| 68 |
+
r"vision_model.vision_tower_low.vision_tower.blocks.(\d+).norm(\d+).(weight|bias)": r"model.vision_model.vision_model.encoder.layers.\1.layer_norm\2.\3",
|
| 69 |
+
r"vision_model.vision_tower_low.vision_tower.blocks.(\d+).mlp.fc(\d+).(weight|bias)": r"model.vision_model.vision_model.encoder.layers.\1.mlp.fc\2.\3",
|
| 70 |
+
r"vision_model.vision_tower_low.vision_tower.norm.(weight|bias)": r"model.vision_model.vision_model.post_layernorm.\1",
|
| 71 |
+
r"vision_model.vision_tower_low.vision_tower.attn_pool.latent": r"model.vision_model.vision_model.head.probe",
|
| 72 |
+
r"vision_model.vision_tower_low.vision_tower.attn_pool.proj.(weight|bias)": r"model.vision_model.vision_model.head.attention.out_proj.\1",
|
| 73 |
+
r"vision_model.vision_tower_low.vision_tower.attn_pool.norm.(weight|bias)": r"model.vision_model.vision_model.head.layernorm.\1",
|
| 74 |
+
r"vision_model.vision_tower_low.vision_tower.attn_pool.mlp.fc(\d+).(weight|bias)": r"model.vision_model.vision_model.head.mlp.fc\1.\2",
|
| 75 |
+
|
| 76 |
+
# Vision Projection
|
| 77 |
+
r"aligner.layers.1.(weight|bias)": r"model.aligner.proj.\1",
|
| 78 |
+
r"aligner.low_up_proj.(weight|bias)": r"model.aligner.vision_proj.\1",
|
| 79 |
+
r"aligner.high_up_proj.(weight|bias)": r"model.aligner.high_res_vision_proj.\1",
|
| 80 |
+
|
| 81 |
+
# Llama (Text Model)
|
| 82 |
+
r"language_model.model.(\w+)": r"model.language_model.\1",
|
| 83 |
+
r"language_model.lm_head.(weight|bias)": r"lm_head.\1",
|
| 84 |
+
}
|
| 85 |
+
# fmt: on
|
| 86 |
+
|
| 87 |
+
# Adopted from https://github.com/deepseek-ai/DeepSeek-VL/blob/main/deepseek_vl/utils/conversation.py#L80-L91
|
| 88 |
+
CHAT_TEMPLATE = (
|
| 89 |
+
# Define separators and initialize counter
|
| 90 |
+
"{% set seps = ['\n\n', '<\uff5cend\u2581of\u2581sentence\uff5c>'] %}"
|
| 91 |
+
"{% set i = 0 %}"
|
| 92 |
+
# Start with default system prompt
|
| 93 |
+
"You are a helpful language and vision assistant. "
|
| 94 |
+
"You are able to understand the visual content that the user provides, "
|
| 95 |
+
"and assist the user with a variety of tasks using natural language.\n\n"
|
| 96 |
+
# Iterate through messages
|
| 97 |
+
"{% for message in messages %}"
|
| 98 |
+
# Identify user or assistant role
|
| 99 |
+
"{% if message['role']|lower == 'user' %}"
|
| 100 |
+
"User: "
|
| 101 |
+
"{% elif message['role']|lower == 'assistant' %}"
|
| 102 |
+
"Assistant:{% if not (loop.last and not add_generation_prompt and message['content'][0]['type']=='text' and message['content'][0]['text']=='') %} {% endif %}"
|
| 103 |
+
"{% else %}"
|
| 104 |
+
"{{ message['role'].capitalize() }}: "
|
| 105 |
+
"{% endif %}"
|
| 106 |
+
# Iterate through message content (text/images)
|
| 107 |
+
"{% for content in message['content'] %}"
|
| 108 |
+
# If content is an image, replace with placeholder
|
| 109 |
+
"{% if content['type'] == 'image' %}"
|
| 110 |
+
"<image_placeholder>"
|
| 111 |
+
# If content is text, handle formatting
|
| 112 |
+
"{% elif content['type'] == 'text' %}"
|
| 113 |
+
"{% set text = content['text'] %}"
|
| 114 |
+
# Strip whitespace for first and last text blocks
|
| 115 |
+
"{% if loop.first %}{% set text = text.lstrip() %}{% endif %}"
|
| 116 |
+
"{% if loop.last %}{% set text = text.rstrip() %}{% endif %}"
|
| 117 |
+
# If previous content was text, add space
|
| 118 |
+
"{% if not loop.first and message['content'][loop.index0-1]['type'] == 'text' %}"
|
| 119 |
+
"{{ ' ' + text }}"
|
| 120 |
+
"{% else %}"
|
| 121 |
+
"{{ text }}"
|
| 122 |
+
"{% endif %}"
|
| 123 |
+
"{% endif %}"
|
| 124 |
+
"{% endfor %}" # End message content loop
|
| 125 |
+
# Add separators between messages
|
| 126 |
+
"{% if not loop.last or add_generation_prompt %}"
|
| 127 |
+
"{% if message['role']|lower == 'user' %}"
|
| 128 |
+
"{{ seps[0] }}"
|
| 129 |
+
"{% else %}"
|
| 130 |
+
"{{ seps[1] }}"
|
| 131 |
+
"{% endif %}"
|
| 132 |
+
"{% endif %}"
|
| 133 |
+
"{% endfor %}" # End messages loop
|
| 134 |
+
# Add final Assistant prompt if required
|
| 135 |
+
"{% if add_generation_prompt %}Assistant:{% endif %}"
|
| 136 |
+
)
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
def convert_old_keys_to_new_keys(state_dict_keys: dict):
|
| 140 |
+
output_dict = {}
|
| 141 |
+
|
| 142 |
+
old_text = "\n".join(state_dict_keys)
|
| 143 |
+
new_text = old_text
|
| 144 |
+
for pattern, replacement in ORIGINAL_TO_CONVERTED_KEY_MAPPING.items():
|
| 145 |
+
if replacement is None:
|
| 146 |
+
new_text = re.sub(pattern, "", new_text) # an empty line
|
| 147 |
+
continue
|
| 148 |
+
new_text = re.sub(pattern, replacement, new_text)
|
| 149 |
+
output_dict = dict(zip(old_text.split("\n"), new_text.split("\n")))
|
| 150 |
+
|
| 151 |
+
return output_dict
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def get_qkv_state_dict(key, parameter):
|
| 155 |
+
"""
|
| 156 |
+
new key which looks like this
|
| 157 |
+
xxxx.(q|k|v).xxx (m, n)
|
| 158 |
+
|
| 159 |
+
is converted to
|
| 160 |
+
xxxx.q.xxxx (m//3, n)
|
| 161 |
+
xxxx.k.xxxx (m//3, n)
|
| 162 |
+
xxxx.v.xxxx (m//3, n)
|
| 163 |
+
"""
|
| 164 |
+
qkv_state_dict = {}
|
| 165 |
+
placeholder = re.search(r"(\(.*?\))", key).group(1) # finds "(query|key|value)"
|
| 166 |
+
replacements_keys = placeholder[1:-1].split("|") # creates ['query', 'key', 'value']
|
| 167 |
+
replacements_vals = torch.split(
|
| 168 |
+
parameter, split_size_or_sections=parameter.size(0) // len(replacements_keys), dim=0
|
| 169 |
+
)
|
| 170 |
+
for replacement_key, replacement_val in zip(replacements_keys, replacements_vals):
|
| 171 |
+
qkv_state_dict[key.replace(placeholder, replacement_key)] = replacement_val
|
| 172 |
+
return qkv_state_dict
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def update_state_dict(old_state_dict):
|
| 176 |
+
all_keys = list(old_state_dict.keys())
|
| 177 |
+
new_keys = convert_old_keys_to_new_keys(all_keys)
|
| 178 |
+
|
| 179 |
+
state_dict = {}
|
| 180 |
+
for key in all_keys:
|
| 181 |
+
new_key = new_keys[key]
|
| 182 |
+
current_parameter = old_state_dict.pop(key)
|
| 183 |
+
|
| 184 |
+
if "qkv" in key and "vision_tower_high" not in key:
|
| 185 |
+
qkv_state_dict = get_qkv_state_dict(new_key, current_parameter)
|
| 186 |
+
state_dict.update(qkv_state_dict)
|
| 187 |
+
elif "pos_embed" in key:
|
| 188 |
+
if "vision_tower_high" not in key:
|
| 189 |
+
# timm implementation of siglip creates this param of size [1, 576, 1024]
|
| 190 |
+
# transformers implementation of siglip creates this param of size [576, 1024]
|
| 191 |
+
state_dict[new_key] = current_parameter.squeeze(0)
|
| 192 |
+
else:
|
| 193 |
+
state_dict[new_key] = current_parameter
|
| 194 |
+
else:
|
| 195 |
+
state_dict[new_key] = current_parameter
|
| 196 |
+
|
| 197 |
+
return state_dict
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
def load_model_state_dict(input_path: str) -> dict:
|
| 201 |
+
"""
|
| 202 |
+
Load model state dict, handling both single and sharded files.
|
| 203 |
+
"""
|
| 204 |
+
index_path = os.path.join(input_path, "model.safetensors.index.json")
|
| 205 |
+
single_file_path = os.path.join(input_path, "model.safetensors")
|
| 206 |
+
|
| 207 |
+
# Check if we have a sharded model
|
| 208 |
+
if os.path.exists(index_path):
|
| 209 |
+
print("Loading sharded model...")
|
| 210 |
+
state_dict = {}
|
| 211 |
+
with open(index_path, "r") as f:
|
| 212 |
+
index = json.load(f)
|
| 213 |
+
|
| 214 |
+
# Get unique shard files and load each one only once
|
| 215 |
+
unique_shard_files = sorted(set(index["weight_map"].values()))
|
| 216 |
+
for shard_file in unique_shard_files:
|
| 217 |
+
print(f"Loading shard {shard_file}...")
|
| 218 |
+
shard_path = os.path.join(input_path, shard_file)
|
| 219 |
+
shard_dict = load_file(shard_path)
|
| 220 |
+
state_dict.update(shard_dict)
|
| 221 |
+
|
| 222 |
+
return state_dict
|
| 223 |
+
|
| 224 |
+
# Single file model
|
| 225 |
+
elif os.path.exists(single_file_path):
|
| 226 |
+
print("Loading single file model...")
|
| 227 |
+
return load_file(single_file_path, device="cpu")
|
| 228 |
+
|
| 229 |
+
else:
|
| 230 |
+
raise ValueError(f"No model files found in {input_path}")
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def convert_model(
|
| 234 |
+
hf_repo_id: str,
|
| 235 |
+
output_dir: str | None = None,
|
| 236 |
+
output_hub_path: str | None = None,
|
| 237 |
+
):
|
| 238 |
+
if output_dir:
|
| 239 |
+
os.makedirs(output_dir, exist_ok=True)
|
| 240 |
+
|
| 241 |
+
try:
|
| 242 |
+
input_path = snapshot_download(hf_repo_id)
|
| 243 |
+
except HFValidationError:
|
| 244 |
+
# If the input path is not a HF repo ID, assume it's a local path
|
| 245 |
+
input_path = hf_repo_id
|
| 246 |
+
|
| 247 |
+
# ------------------------------------------------------------
|
| 248 |
+
# Create and save config
|
| 249 |
+
# ------------------------------------------------------------
|
| 250 |
+
|
| 251 |
+
config = DeepseekVLHybridConfig(
|
| 252 |
+
text_config={
|
| 253 |
+
"hidden_size": 4096,
|
| 254 |
+
"intermediate_size": 11008,
|
| 255 |
+
"max_position_embeddings": 16384,
|
| 256 |
+
"num_attention_heads": 32,
|
| 257 |
+
"num_hidden_layers": 30,
|
| 258 |
+
"vocab_size": 102400,
|
| 259 |
+
},
|
| 260 |
+
vision_config={
|
| 261 |
+
"hidden_size": 1024,
|
| 262 |
+
"intermediate_size": 4096,
|
| 263 |
+
"image_size": 384,
|
| 264 |
+
"patch_size": 16,
|
| 265 |
+
"hidden_act": "gelu",
|
| 266 |
+
"vision_use_head": False,
|
| 267 |
+
"num_attention_heads": 16,
|
| 268 |
+
"num_hidden_layers": 24,
|
| 269 |
+
},
|
| 270 |
+
high_res_vision_config={
|
| 271 |
+
"hidden_size": 768,
|
| 272 |
+
"intermediate_size": 3072,
|
| 273 |
+
"image_size": 1024,
|
| 274 |
+
"patch_size": 16,
|
| 275 |
+
"num_attention_heads": 12,
|
| 276 |
+
"num_hidden_layers": 12,
|
| 277 |
+
},
|
| 278 |
+
)
|
| 279 |
+
|
| 280 |
+
# save config
|
| 281 |
+
if output_dir:
|
| 282 |
+
config.save_pretrained(output_dir)
|
| 283 |
+
print("Model config saved successfully...")
|
| 284 |
+
|
| 285 |
+
# ------------------------------------------------------------
|
| 286 |
+
# Convert processor
|
| 287 |
+
# ------------------------------------------------------------
|
| 288 |
+
|
| 289 |
+
image_processor = DeepseekVLHybridImageProcessor(
|
| 290 |
+
image_mean=IMAGENET_STANDARD_MEAN,
|
| 291 |
+
image_std=IMAGENET_STANDARD_STD,
|
| 292 |
+
high_res_image_mean=OPENAI_CLIP_MEAN,
|
| 293 |
+
high_res_image_std=OPENAI_CLIP_STD,
|
| 294 |
+
resample=PILImageResampling.BILINEAR,
|
| 295 |
+
)
|
| 296 |
+
|
| 297 |
+
tokenizer = AutoTokenizer.from_pretrained(
|
| 298 |
+
input_path,
|
| 299 |
+
extra_special_tokens={
|
| 300 |
+
"pad_token": "<|end▁of▁sentence|>",
|
| 301 |
+
"image_token": "<image_placeholder>",
|
| 302 |
+
},
|
| 303 |
+
)
|
| 304 |
+
|
| 305 |
+
processor = DeepseekVLHybridProcessor(
|
| 306 |
+
image_processor=image_processor,
|
| 307 |
+
tokenizer=tokenizer,
|
| 308 |
+
chat_template=CHAT_TEMPLATE,
|
| 309 |
+
)
|
| 310 |
+
|
| 311 |
+
if output_dir:
|
| 312 |
+
print(f"Saving processor to {output_dir}...")
|
| 313 |
+
processor.save_pretrained(output_dir)
|
| 314 |
+
if output_hub_path:
|
| 315 |
+
print(f"Pushing processor to hub at {output_hub_path}...")
|
| 316 |
+
processor.push_to_hub(output_hub_path)
|
| 317 |
+
|
| 318 |
+
# ------------------------------------------------------------
|
| 319 |
+
# Convert weights
|
| 320 |
+
# ------------------------------------------------------------
|
| 321 |
+
|
| 322 |
+
print("Creating empty model...")
|
| 323 |
+
with torch.device("meta"):
|
| 324 |
+
model = DeepseekVLHybridForConditionalGeneration(config)
|
| 325 |
+
|
| 326 |
+
# Load and convert state dict
|
| 327 |
+
print("Loading state dict...")
|
| 328 |
+
state_dict = load_model_state_dict(input_path)
|
| 329 |
+
state_dict = update_state_dict(state_dict)
|
| 330 |
+
|
| 331 |
+
# Load converted state dict
|
| 332 |
+
print("Loading converted weights into model...")
|
| 333 |
+
info = model.load_state_dict(state_dict, strict=False, assign=True)
|
| 334 |
+
if len(info.missing_keys) > 0:
|
| 335 |
+
raise ValueError(f"Missing keys: {info.missing_keys}")
|
| 336 |
+
|
| 337 |
+
# Tie weights before any device mapping
|
| 338 |
+
print("Tying weights...")
|
| 339 |
+
model.tie_weights()
|
| 340 |
+
|
| 341 |
+
# Save the model
|
| 342 |
+
if output_dir:
|
| 343 |
+
print(f"Saving model to {output_dir}...")
|
| 344 |
+
model.save_pretrained(output_dir)
|
| 345 |
+
if output_hub_path:
|
| 346 |
+
print(f"Pushing model to hub at {output_hub_path}...")
|
| 347 |
+
model.push_to_hub(output_hub_path)
|
| 348 |
+
|
| 349 |
+
del state_dict, model
|
| 350 |
+
gc.collect()
|
| 351 |
+
|
| 352 |
+
# Validate the saved model if saved locally
|
| 353 |
+
if output_dir:
|
| 354 |
+
print("Reloading the local model to check if it's saved correctly...")
|
| 355 |
+
DeepseekVLHybridForConditionalGeneration.from_pretrained(output_dir, device_map="auto")
|
| 356 |
+
print("Local model reloaded successfully.")
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
def main():
|
| 360 |
+
parser = argparse.ArgumentParser()
|
| 361 |
+
parser.add_argument(
|
| 362 |
+
"--hf_repo_id",
|
| 363 |
+
default="deepseek-ai/deepseek-vl-7b-chat",
|
| 364 |
+
help="Location of official weights from DeepseekAI on HF",
|
| 365 |
+
)
|
| 366 |
+
parser.add_argument(
|
| 367 |
+
"--output_dir",
|
| 368 |
+
default=None,
|
| 369 |
+
help="Location to write the converted model and processor",
|
| 370 |
+
)
|
| 371 |
+
parser.add_argument(
|
| 372 |
+
"--output_hub_path",
|
| 373 |
+
default=None,
|
| 374 |
+
help="Repository ID to push model to hub (e.g. 'username/model-name')",
|
| 375 |
+
)
|
| 376 |
+
args = parser.parse_args()
|
| 377 |
+
|
| 378 |
+
convert_model(
|
| 379 |
+
hf_repo_id=args.hf_repo_id,
|
| 380 |
+
output_dir=args.output_dir,
|
| 381 |
+
output_hub_path=args.output_hub_path,
|
| 382 |
+
)
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
if __name__ == "__main__":
|
| 386 |
+
main()
|
third_party/transformers/src/transformers/models/deepseek_vl_hybrid/image_processing_deepseek_vl_hybrid.py
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.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_deepseek_vl_hybrid.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 Deepseek AI and The HuggingFace Team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from collections.abc import Iterable
|
| 22 |
+
from typing import Union
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
import torchvision.transforms.v2.functional as tvF
|
| 26 |
+
|
| 27 |
+
from ...image_processing_backends import TorchvisionBackend
|
| 28 |
+
from ...image_processing_utils import BatchFeature, get_size_dict
|
| 29 |
+
from ...image_transforms import group_images_by_shape, reorder_images
|
| 30 |
+
from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling, SizeDict
|
| 31 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 32 |
+
from ...utils import TensorType, auto_docstring
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class DeepseekVLHybridImageProcessorKwargs(ImagesKwargs, total=False):
|
| 36 |
+
r"""
|
| 37 |
+
min_size (`int`, *optional*, defaults to 14):
|
| 38 |
+
The minimum allowed size for the resized image. Ensures that neither the height nor width
|
| 39 |
+
falls below this value after resizing.
|
| 40 |
+
high_res_size (`dict`, *optional*, defaults to `{"height": 1024, "width": 1024}`):
|
| 41 |
+
Size of the high resolution output image after resizing. Can be overridden by the `high_res_size` parameter in the `preprocess`
|
| 42 |
+
method.
|
| 43 |
+
high_res_resample (`PILImageResampling`, *optional*, defaults to `Resampling.BICUBIC`):
|
| 44 |
+
Resampling filter to use if resizing the image. Only has an effect if `do_resize` is set to `True`. Can be
|
| 45 |
+
overridden by the `high_res_resample` parameter in the `preprocess` method.
|
| 46 |
+
high_res_image_mean (`float` or `list[float]`, *optional*, defaults to `OPENAI_CLIP_MEAN`):
|
| 47 |
+
Mean to use if normalizing the high resolution image. This is a float or list of floats the length of the number of
|
| 48 |
+
channels in the image. Can be overridden by the `high_res_image_mean` parameter in the `preprocess` method.
|
| 49 |
+
high_res_image_std (`float` or `list[float]`, *optional*, defaults to `OPENAI_CLIP_STD`):
|
| 50 |
+
Standard deviation to use if normalizing the high resolution image. This is a float or list of floats the length of the
|
| 51 |
+
number of channels in the image. Can be overridden by the `high_res_image_std` parameter in the `preprocess` method.
|
| 52 |
+
"""
|
| 53 |
+
|
| 54 |
+
min_size: int
|
| 55 |
+
high_res_size: dict
|
| 56 |
+
high_res_resample: Union["PILImageResampling", int]
|
| 57 |
+
high_res_image_mean: float | list[float] | tuple[float, ...]
|
| 58 |
+
high_res_image_std: float | list[float] | tuple[float, ...]
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
@auto_docstring
|
| 62 |
+
class DeepseekVLHybridImageProcessor(TorchvisionBackend):
|
| 63 |
+
resample = PILImageResampling.BICUBIC
|
| 64 |
+
image_mean = OPENAI_CLIP_MEAN
|
| 65 |
+
image_std = OPENAI_CLIP_STD
|
| 66 |
+
size = {"height": 384, "width": 384}
|
| 67 |
+
min_size = 14
|
| 68 |
+
do_resize = True
|
| 69 |
+
do_rescale = True
|
| 70 |
+
do_normalize = True
|
| 71 |
+
do_pad = True
|
| 72 |
+
valid_kwargs = DeepseekVLHybridImageProcessorKwargs
|
| 73 |
+
high_res_image_mean = OPENAI_CLIP_MEAN
|
| 74 |
+
high_res_image_std = OPENAI_CLIP_STD
|
| 75 |
+
high_res_size = {"height": 1024, "width": 1024}
|
| 76 |
+
high_res_resample = PILImageResampling.BICUBIC
|
| 77 |
+
model_input_names = ["pixel_values", "high_res_pixel_values"]
|
| 78 |
+
|
| 79 |
+
def __init__(self, **kwargs: Unpack[DeepseekVLHybridImageProcessorKwargs]):
|
| 80 |
+
if kwargs.get("image_mean") is None:
|
| 81 |
+
background_color = (127, 127, 127)
|
| 82 |
+
else:
|
| 83 |
+
background_color = tuple(int(x * 255) for x in kwargs.get("image_mean"))
|
| 84 |
+
if kwargs.get("high_res_image_mean") is None:
|
| 85 |
+
high_res_background_color = (127, 127, 127)
|
| 86 |
+
else:
|
| 87 |
+
high_res_background_color = tuple(int(x * 255) for x in kwargs.get("high_res_image_mean"))
|
| 88 |
+
super().__init__(**kwargs)
|
| 89 |
+
self.background_color = tuple(background_color)
|
| 90 |
+
self.high_res_background_color = tuple(high_res_background_color)
|
| 91 |
+
|
| 92 |
+
def resize(
|
| 93 |
+
self,
|
| 94 |
+
image: "torch.Tensor",
|
| 95 |
+
size: SizeDict,
|
| 96 |
+
min_size: int,
|
| 97 |
+
resample: "PILImageResampling | tvF.InterpolationMode | int | None",
|
| 98 |
+
antialias: bool = True,
|
| 99 |
+
**kwargs,
|
| 100 |
+
) -> "torch.Tensor":
|
| 101 |
+
if size.height is None or size.width is None or size.height != size.width:
|
| 102 |
+
raise ValueError(
|
| 103 |
+
f"Output height and width must be the same. Got height={size['height']} and width={size['width']}"
|
| 104 |
+
)
|
| 105 |
+
size = size.height
|
| 106 |
+
|
| 107 |
+
height, width = image.shape[-2:]
|
| 108 |
+
max_size = max(height, width)
|
| 109 |
+
|
| 110 |
+
delta = size / max_size
|
| 111 |
+
# Largest side becomes `size` and the other side is scaled according to the aspect ratio.
|
| 112 |
+
output_size_nonpadded = SizeDict(
|
| 113 |
+
height=max(round(height * delta), min_size),
|
| 114 |
+
width=max(round(width * delta), min_size),
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
return super().resize(image, size=output_size_nonpadded, resample=resample, antialias=antialias)
|
| 118 |
+
|
| 119 |
+
def pad_to_square(
|
| 120 |
+
self,
|
| 121 |
+
images: "torch.Tensor",
|
| 122 |
+
background_color: int | tuple[int, int, int] = 0,
|
| 123 |
+
) -> "torch.Tensor":
|
| 124 |
+
"""
|
| 125 |
+
Pads an image to a square based on the longest edge.
|
| 126 |
+
|
| 127 |
+
Args:
|
| 128 |
+
images (`torch.Tensor`):
|
| 129 |
+
The images to pad.
|
| 130 |
+
background_color (`int` or `tuple[int, int, int]`, *optional*, defaults to 0):
|
| 131 |
+
The color to use for the padding. Can be an integer for single channel or a
|
| 132 |
+
tuple of integers representing for multi-channel images. If passed as integer
|
| 133 |
+
in multi-channel mode, it will default to `0` in subsequent channels.
|
| 134 |
+
|
| 135 |
+
Returns:
|
| 136 |
+
`torch.Tensor`: The padded images.
|
| 137 |
+
"""
|
| 138 |
+
height, width = images.shape[-2:]
|
| 139 |
+
num_channels = images.shape[1]
|
| 140 |
+
batch_size = images.shape[0]
|
| 141 |
+
|
| 142 |
+
if height == width:
|
| 143 |
+
return images
|
| 144 |
+
|
| 145 |
+
max_dim = max(height, width)
|
| 146 |
+
|
| 147 |
+
# Ensure background_color is the correct shape
|
| 148 |
+
if isinstance(background_color, int):
|
| 149 |
+
background_color = [background_color]
|
| 150 |
+
elif len(background_color) != num_channels:
|
| 151 |
+
raise ValueError(
|
| 152 |
+
f"background_color must have no more than {num_channels} elements to match the number of channels"
|
| 153 |
+
)
|
| 154 |
+
|
| 155 |
+
padded_images = torch.zeros(
|
| 156 |
+
(batch_size, num_channels, max_dim, max_dim), dtype=images.dtype, device=images.device
|
| 157 |
+
)
|
| 158 |
+
for i, color in enumerate(background_color):
|
| 159 |
+
padded_images[:, i, :, :] = color
|
| 160 |
+
if width > height:
|
| 161 |
+
start = (max_dim - height) // 2
|
| 162 |
+
padded_images[:, :, start : start + height, :] = images
|
| 163 |
+
else:
|
| 164 |
+
start = (max_dim - width) // 2
|
| 165 |
+
padded_images[:, :, :, start : start + width] = images
|
| 166 |
+
|
| 167 |
+
return padded_images
|
| 168 |
+
|
| 169 |
+
def _preprocess(
|
| 170 |
+
self,
|
| 171 |
+
images: list["torch.Tensor"],
|
| 172 |
+
do_resize: bool,
|
| 173 |
+
size: SizeDict,
|
| 174 |
+
high_res_size: SizeDict,
|
| 175 |
+
min_size: int,
|
| 176 |
+
resample: "PILImageResampling | None",
|
| 177 |
+
high_res_resample: "PILImageResampling | None",
|
| 178 |
+
do_rescale: bool,
|
| 179 |
+
rescale_factor: float,
|
| 180 |
+
do_normalize: bool,
|
| 181 |
+
image_mean: float | list[float] | None,
|
| 182 |
+
image_std: float | list[float] | None,
|
| 183 |
+
high_res_image_mean: float | list[float] | None,
|
| 184 |
+
high_res_image_std: float | list[float] | None,
|
| 185 |
+
disable_grouping: bool | None,
|
| 186 |
+
return_tensors: str | TensorType | None,
|
| 187 |
+
do_pad: bool = True,
|
| 188 |
+
**kwargs,
|
| 189 |
+
) -> BatchFeature:
|
| 190 |
+
# Group images by size for batched resizing
|
| 191 |
+
grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
|
| 192 |
+
high_res_resized_images_grouped = {}
|
| 193 |
+
for shape, stacked_images in grouped_images.items():
|
| 194 |
+
if do_resize:
|
| 195 |
+
stacked_high_res_images = self.resize(
|
| 196 |
+
image=stacked_images, size=high_res_size, min_size=min_size, resample=high_res_resample
|
| 197 |
+
)
|
| 198 |
+
high_res_resized_images_grouped[shape] = stacked_high_res_images
|
| 199 |
+
high_res_resized_images = reorder_images(high_res_resized_images_grouped, grouped_images_index)
|
| 200 |
+
|
| 201 |
+
# Group images by size for further processing
|
| 202 |
+
# Needed in case do_resize is False, or resize returns images with different sizes
|
| 203 |
+
grouped_high_res_images, grouped_high_res_images_index = group_images_by_shape(
|
| 204 |
+
high_res_resized_images, disable_grouping=disable_grouping
|
| 205 |
+
)
|
| 206 |
+
high_res_padded_images = {}
|
| 207 |
+
high_res_processed_images_grouped = {}
|
| 208 |
+
for shape, stacked_high_res_images in grouped_high_res_images.items():
|
| 209 |
+
if do_pad:
|
| 210 |
+
stacked_high_res_images = self.pad_to_square(
|
| 211 |
+
stacked_high_res_images, background_color=self.high_res_background_color
|
| 212 |
+
)
|
| 213 |
+
high_res_padded_images[shape] = stacked_high_res_images
|
| 214 |
+
# Fused rescale and normalize
|
| 215 |
+
stacked_high_res_images = self.rescale_and_normalize(
|
| 216 |
+
stacked_high_res_images,
|
| 217 |
+
do_rescale,
|
| 218 |
+
rescale_factor,
|
| 219 |
+
do_normalize,
|
| 220 |
+
high_res_image_mean,
|
| 221 |
+
high_res_image_std,
|
| 222 |
+
)
|
| 223 |
+
high_res_processed_images_grouped[shape] = stacked_high_res_images
|
| 224 |
+
high_res_processed_images = reorder_images(high_res_processed_images_grouped, grouped_high_res_images_index)
|
| 225 |
+
|
| 226 |
+
resized_images_grouped = {}
|
| 227 |
+
for shape, stacked_high_res_padded_images in high_res_padded_images.items():
|
| 228 |
+
if do_resize:
|
| 229 |
+
stacked_images = self.resize(
|
| 230 |
+
image=stacked_high_res_padded_images, size=size, min_size=min_size, resample=resample
|
| 231 |
+
)
|
| 232 |
+
resized_images_grouped[shape] = stacked_images
|
| 233 |
+
resized_images = reorder_images(resized_images_grouped, grouped_high_res_images_index)
|
| 234 |
+
|
| 235 |
+
grouped_resized_images, grouped_resized_images_index = group_images_by_shape(
|
| 236 |
+
resized_images, disable_grouping=disable_grouping
|
| 237 |
+
)
|
| 238 |
+
processed_images_grouped = {}
|
| 239 |
+
for shape, stacked_images in grouped_resized_images.items():
|
| 240 |
+
if do_pad:
|
| 241 |
+
stacked_images = self.pad_to_square(stacked_images, background_color=self.background_color)
|
| 242 |
+
# Fused rescale and normalize
|
| 243 |
+
stacked_images = self.rescale_and_normalize(
|
| 244 |
+
stacked_images, do_rescale, rescale_factor, do_normalize, image_mean, image_std
|
| 245 |
+
)
|
| 246 |
+
processed_images_grouped[shape] = stacked_images
|
| 247 |
+
processed_images = reorder_images(processed_images_grouped, grouped_resized_images_index)
|
| 248 |
+
|
| 249 |
+
return BatchFeature(
|
| 250 |
+
data={"pixel_values": processed_images, "high_res_pixel_values": high_res_processed_images},
|
| 251 |
+
tensor_type=return_tensors,
|
| 252 |
+
)
|
| 253 |
+
|
| 254 |
+
def postprocess(self) -> "torch.Tensor":
|
| 255 |
+
raise AttributeError("Not needed for DeepseekVLHybrid")
|
| 256 |
+
|
| 257 |
+
def _standardize_kwargs(
|
| 258 |
+
self,
|
| 259 |
+
size: int | Iterable[int] | dict[str, int] | SizeDict | None = None,
|
| 260 |
+
high_res_size: int | Iterable[int] | dict[str, int] | SizeDict | None = None,
|
| 261 |
+
default_to_square: bool | None = None,
|
| 262 |
+
image_mean: float | list[float] | None = None,
|
| 263 |
+
image_std: float | list[float] | None = None,
|
| 264 |
+
high_res_image_mean: float | list[float] | None = None,
|
| 265 |
+
high_res_image_std: float | list[float] | None = None,
|
| 266 |
+
**kwargs,
|
| 267 |
+
) -> dict:
|
| 268 |
+
"""
|
| 269 |
+
Update kwargs that need further processing before being validated
|
| 270 |
+
Can be overridden by subclasses to customize the processing of kwargs.
|
| 271 |
+
"""
|
| 272 |
+
if kwargs is None:
|
| 273 |
+
kwargs = {}
|
| 274 |
+
if size is not None and not isinstance(size, SizeDict):
|
| 275 |
+
size = SizeDict(**get_size_dict(size=size, default_to_square=default_to_square))
|
| 276 |
+
if high_res_size is not None and not isinstance(high_res_size, SizeDict):
|
| 277 |
+
high_res_size = SizeDict(**get_size_dict(size=high_res_size, default_to_square=default_to_square))
|
| 278 |
+
if isinstance(image_mean, list):
|
| 279 |
+
image_mean = tuple(image_mean)
|
| 280 |
+
if isinstance(image_std, list):
|
| 281 |
+
image_std = tuple(image_std)
|
| 282 |
+
if isinstance(high_res_image_mean, list):
|
| 283 |
+
high_res_image_mean = tuple(high_res_image_mean)
|
| 284 |
+
if isinstance(high_res_image_std, list):
|
| 285 |
+
high_res_image_std = tuple(high_res_image_std)
|
| 286 |
+
|
| 287 |
+
kwargs["size"] = size
|
| 288 |
+
kwargs["high_res_size"] = high_res_size
|
| 289 |
+
kwargs["image_mean"] = image_mean
|
| 290 |
+
kwargs["image_std"] = image_std
|
| 291 |
+
kwargs["high_res_image_mean"] = high_res_image_mean
|
| 292 |
+
kwargs["high_res_image_std"] = high_res_image_std
|
| 293 |
+
|
| 294 |
+
return kwargs
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
__all__ = ["DeepseekVLHybridImageProcessor"]
|
third_party/transformers/src/transformers/models/deepseek_vl_hybrid/image_processing_pil_deepseek_vl_hybrid.py
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.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_deepseek_vl_hybrid.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 Deepseek AI and The HuggingFace Team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from collections.abc import Iterable
|
| 22 |
+
from typing import Union
|
| 23 |
+
|
| 24 |
+
import numpy as np
|
| 25 |
+
|
| 26 |
+
from ...image_processing_backends import PilBackend
|
| 27 |
+
from ...image_processing_utils import BatchFeature, get_size_dict
|
| 28 |
+
from ...image_transforms import resize as np_resize
|
| 29 |
+
from ...image_utils import (
|
| 30 |
+
OPENAI_CLIP_MEAN,
|
| 31 |
+
OPENAI_CLIP_STD,
|
| 32 |
+
ChannelDimension,
|
| 33 |
+
ImageInput,
|
| 34 |
+
PILImageResampling,
|
| 35 |
+
SizeDict,
|
| 36 |
+
)
|
| 37 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 38 |
+
from ...utils import TensorType, auto_docstring
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class DeepseekVLHybridImageProcessorKwargs(ImagesKwargs, total=False):
|
| 42 |
+
r"""
|
| 43 |
+
min_size (`int`, *optional*, defaults to 14):
|
| 44 |
+
The minimum allowed size for the resized image. Ensures that neither the height nor width
|
| 45 |
+
falls below this value after resizing.
|
| 46 |
+
high_res_size (`dict`, *optional*, defaults to `{"height": 1024, "width": 1024}`):
|
| 47 |
+
Size of the high resolution output image after resizing. Can be overridden by the `high_res_size` parameter in the `preprocess`
|
| 48 |
+
method.
|
| 49 |
+
high_res_resample (`PILImageResampling`, *optional*, defaults to `Resampling.BICUBIC`):
|
| 50 |
+
Resampling filter to use if resizing the image. Only has an effect if `do_resize` is set to `True`. Can be
|
| 51 |
+
overridden by the `high_res_resample` parameter in the `preprocess` method.
|
| 52 |
+
high_res_image_mean (`float` or `list[float]`, *optional*, defaults to `OPENAI_CLIP_MEAN`):
|
| 53 |
+
Mean to use if normalizing the high resolution image. This is a float or list of floats the length of the number of
|
| 54 |
+
channels in the image. Can be overridden by the `high_res_image_mean` parameter in the `preprocess` method.
|
| 55 |
+
high_res_image_std (`float` or `list[float]`, *optional*, defaults to `OPENAI_CLIP_STD`):
|
| 56 |
+
Standard deviation to use if normalizing the high resolution image. This is a float or list of floats the length of the
|
| 57 |
+
number of channels in the image. Can be overridden by the `high_res_image_std` parameter in the `preprocess` method.
|
| 58 |
+
"""
|
| 59 |
+
|
| 60 |
+
min_size: int
|
| 61 |
+
high_res_size: dict
|
| 62 |
+
high_res_resample: Union["PILImageResampling", int]
|
| 63 |
+
high_res_image_mean: float | list[float] | tuple[float, ...]
|
| 64 |
+
high_res_image_std: float | list[float] | tuple[float, ...]
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
@auto_docstring
|
| 68 |
+
class DeepseekVLHybridImageProcessorPil(PilBackend):
|
| 69 |
+
resample = PILImageResampling.BICUBIC
|
| 70 |
+
image_mean = OPENAI_CLIP_MEAN
|
| 71 |
+
image_std = OPENAI_CLIP_STD
|
| 72 |
+
size = {"height": 384, "width": 384}
|
| 73 |
+
min_size = 14
|
| 74 |
+
do_resize = True
|
| 75 |
+
do_rescale = True
|
| 76 |
+
do_normalize = True
|
| 77 |
+
do_pad = True
|
| 78 |
+
valid_kwargs = DeepseekVLHybridImageProcessorKwargs
|
| 79 |
+
high_res_image_mean = OPENAI_CLIP_MEAN
|
| 80 |
+
high_res_image_std = OPENAI_CLIP_STD
|
| 81 |
+
high_res_size = {"height": 1024, "width": 1024}
|
| 82 |
+
high_res_resample = PILImageResampling.BICUBIC
|
| 83 |
+
model_input_names = ["pixel_values", "high_res_pixel_values"]
|
| 84 |
+
|
| 85 |
+
def __init__(self, **kwargs: Unpack[DeepseekVLHybridImageProcessorKwargs]):
|
| 86 |
+
if kwargs.get("image_mean") is None:
|
| 87 |
+
background_color = (127, 127, 127)
|
| 88 |
+
else:
|
| 89 |
+
background_color = tuple(int(x * 255) for x in kwargs.get("image_mean"))
|
| 90 |
+
if kwargs.get("high_res_image_mean") is None:
|
| 91 |
+
high_res_background_color = (127, 127, 127)
|
| 92 |
+
else:
|
| 93 |
+
high_res_background_color = tuple(int(x * 255) for x in kwargs.get("high_res_image_mean"))
|
| 94 |
+
super().__init__(**kwargs)
|
| 95 |
+
self.background_color = tuple(background_color)
|
| 96 |
+
self.high_res_background_color = tuple(high_res_background_color)
|
| 97 |
+
|
| 98 |
+
@auto_docstring
|
| 99 |
+
def preprocess(self, images: ImageInput, **kwargs: Unpack[DeepseekVLHybridImageProcessorKwargs]) -> BatchFeature:
|
| 100 |
+
return super().preprocess(images, **kwargs)
|
| 101 |
+
|
| 102 |
+
def resize(
|
| 103 |
+
self,
|
| 104 |
+
image: np.ndarray,
|
| 105 |
+
size: SizeDict,
|
| 106 |
+
min_size: int,
|
| 107 |
+
resample: PILImageResampling | None = None,
|
| 108 |
+
**kwargs,
|
| 109 |
+
) -> np.ndarray:
|
| 110 |
+
"""Resize so largest side becomes size, with min_size floor."""
|
| 111 |
+
if size.height is None or size.width is None or size.height != size.width:
|
| 112 |
+
raise ValueError(
|
| 113 |
+
f"Output height and width must be the same. Got height={size.height} and width={size.width}"
|
| 114 |
+
)
|
| 115 |
+
target_size = size.height
|
| 116 |
+
|
| 117 |
+
height, width = image.shape[-2:]
|
| 118 |
+
max_size = max(height, width)
|
| 119 |
+
|
| 120 |
+
delta = target_size / max_size
|
| 121 |
+
new_height = max(round(height * delta), min_size)
|
| 122 |
+
new_width = max(round(width * delta), min_size)
|
| 123 |
+
|
| 124 |
+
return np_resize(
|
| 125 |
+
image,
|
| 126 |
+
size=(new_height, new_width),
|
| 127 |
+
resample=resample or self.resample,
|
| 128 |
+
data_format=ChannelDimension.FIRST,
|
| 129 |
+
input_data_format=ChannelDimension.FIRST,
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
def pad_to_square(
|
| 133 |
+
self,
|
| 134 |
+
image: np.ndarray,
|
| 135 |
+
background_color: int | tuple[int, int, int] = 0,
|
| 136 |
+
) -> np.ndarray:
|
| 137 |
+
"""Pad an image to a square based on the longest edge."""
|
| 138 |
+
height, width = image.shape[-2:]
|
| 139 |
+
num_channels = image.shape[0]
|
| 140 |
+
|
| 141 |
+
if height == width:
|
| 142 |
+
return image
|
| 143 |
+
|
| 144 |
+
max_dim = max(height, width)
|
| 145 |
+
|
| 146 |
+
if isinstance(background_color, int):
|
| 147 |
+
background_color = [background_color]
|
| 148 |
+
elif len(background_color) != num_channels:
|
| 149 |
+
raise ValueError(
|
| 150 |
+
f"background_color must have no more than {num_channels} elements to match the number of channels"
|
| 151 |
+
)
|
| 152 |
+
|
| 153 |
+
padded_image = np.zeros((num_channels, max_dim, max_dim), dtype=image.dtype)
|
| 154 |
+
for i, color in enumerate(background_color):
|
| 155 |
+
padded_image[i, :, :] = color
|
| 156 |
+
|
| 157 |
+
if width > height:
|
| 158 |
+
start = (max_dim - height) // 2
|
| 159 |
+
padded_image[:, start : start + height, :] = image
|
| 160 |
+
else:
|
| 161 |
+
start = (max_dim - width) // 2
|
| 162 |
+
padded_image[:, :, start : start + width] = image
|
| 163 |
+
|
| 164 |
+
return padded_image
|
| 165 |
+
|
| 166 |
+
def _preprocess(
|
| 167 |
+
self,
|
| 168 |
+
images: list[np.ndarray],
|
| 169 |
+
do_resize: bool,
|
| 170 |
+
size: SizeDict,
|
| 171 |
+
high_res_size: SizeDict,
|
| 172 |
+
min_size: int,
|
| 173 |
+
resample: "PILImageResampling | None",
|
| 174 |
+
high_res_resample: "PILImageResampling | None",
|
| 175 |
+
do_rescale: bool,
|
| 176 |
+
rescale_factor: float,
|
| 177 |
+
do_normalize: bool,
|
| 178 |
+
image_mean: float | list[float] | None,
|
| 179 |
+
image_std: float | list[float] | None,
|
| 180 |
+
high_res_image_mean: float | list[float] | None,
|
| 181 |
+
high_res_image_std: float | list[float] | None,
|
| 182 |
+
return_tensors: str | TensorType | None,
|
| 183 |
+
do_pad: bool = True,
|
| 184 |
+
**kwargs,
|
| 185 |
+
) -> BatchFeature:
|
| 186 |
+
high_res_processed_images = []
|
| 187 |
+
processed_images = []
|
| 188 |
+
for image in images:
|
| 189 |
+
# high_res_image: resize (high) -> rescale -> normalize (high)
|
| 190 |
+
# low_res_image: resize (high) -> rescale -> resize (low) -> normalize (low)
|
| 191 |
+
high_res_image = image
|
| 192 |
+
if do_resize:
|
| 193 |
+
high_res_image = self.resize(
|
| 194 |
+
image=high_res_image, size=high_res_size, min_size=min_size, resample=high_res_resample
|
| 195 |
+
)
|
| 196 |
+
if do_pad:
|
| 197 |
+
high_res_image = self.pad_to_square(
|
| 198 |
+
high_res_image, background_color=self.high_res_background_color
|
| 199 |
+
)
|
| 200 |
+
image = self.resize(image=high_res_image, size=size, min_size=min_size, resample=resample)
|
| 201 |
+
if do_pad:
|
| 202 |
+
image = self.pad_to_square(image, background_color=self.background_color)
|
| 203 |
+
if do_rescale:
|
| 204 |
+
high_res_image = self.rescale(high_res_image, rescale_factor)
|
| 205 |
+
image = self.rescale(image, rescale_factor)
|
| 206 |
+
if do_normalize:
|
| 207 |
+
high_res_image = self.normalize(high_res_image, high_res_image_mean, high_res_image_std)
|
| 208 |
+
image = self.normalize(image, image_mean, image_std)
|
| 209 |
+
processed_images.append(image)
|
| 210 |
+
high_res_processed_images.append(high_res_image)
|
| 211 |
+
|
| 212 |
+
return BatchFeature(
|
| 213 |
+
data={"pixel_values": processed_images, "high_res_pixel_values": high_res_processed_images},
|
| 214 |
+
tensor_type=return_tensors,
|
| 215 |
+
)
|
| 216 |
+
|
| 217 |
+
def postprocess(self):
|
| 218 |
+
"""Applies post-processing to the decoded image tokens by reversing transformations applied during preprocessing."""
|
| 219 |
+
raise AttributeError("Not needed for DeepseekVLHybrid")
|
| 220 |
+
|
| 221 |
+
def _standardize_kwargs(
|
| 222 |
+
self,
|
| 223 |
+
size: int | Iterable[int] | dict[str, int] | SizeDict | None = None,
|
| 224 |
+
high_res_size: int | Iterable[int] | dict[str, int] | SizeDict | None = None,
|
| 225 |
+
default_to_square: bool | None = None,
|
| 226 |
+
image_mean: float | list[float] | None = None,
|
| 227 |
+
image_std: float | list[float] | None = None,
|
| 228 |
+
high_res_image_mean: float | list[float] | None = None,
|
| 229 |
+
high_res_image_std: float | list[float] | None = None,
|
| 230 |
+
**kwargs,
|
| 231 |
+
) -> dict:
|
| 232 |
+
"""
|
| 233 |
+
Update kwargs that need further processing before being validated
|
| 234 |
+
Can be overridden by subclasses to customize the processing of kwargs.
|
| 235 |
+
"""
|
| 236 |
+
if kwargs is None:
|
| 237 |
+
kwargs = {}
|
| 238 |
+
if size is not None and not isinstance(size, SizeDict):
|
| 239 |
+
size = SizeDict(**get_size_dict(size=size, default_to_square=default_to_square))
|
| 240 |
+
if high_res_size is not None and not isinstance(high_res_size, SizeDict):
|
| 241 |
+
high_res_size = SizeDict(**get_size_dict(size=high_res_size, default_to_square=default_to_square))
|
| 242 |
+
if isinstance(image_mean, list):
|
| 243 |
+
image_mean = tuple(image_mean)
|
| 244 |
+
if isinstance(image_std, list):
|
| 245 |
+
image_std = tuple(image_std)
|
| 246 |
+
if isinstance(high_res_image_mean, list):
|
| 247 |
+
high_res_image_mean = tuple(high_res_image_mean)
|
| 248 |
+
if isinstance(high_res_image_std, list):
|
| 249 |
+
high_res_image_std = tuple(high_res_image_std)
|
| 250 |
+
|
| 251 |
+
kwargs["size"] = size
|
| 252 |
+
kwargs["high_res_size"] = high_res_size
|
| 253 |
+
kwargs["image_mean"] = image_mean
|
| 254 |
+
kwargs["image_std"] = image_std
|
| 255 |
+
kwargs["high_res_image_mean"] = high_res_image_mean
|
| 256 |
+
kwargs["high_res_image_std"] = high_res_image_std
|
| 257 |
+
|
| 258 |
+
return kwargs
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
__all__ = ["DeepseekVLHybridImageProcessorPil"]
|
third_party/transformers/src/transformers/models/deepseek_vl_hybrid/modeling_deepseek_vl_hybrid.py
ADDED
|
@@ -0,0 +1,539 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.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_deepseek_vl_hybrid.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 Deepseek AI and The HuggingFace Team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from dataclasses import dataclass
|
| 22 |
+
|
| 23 |
+
import torch
|
| 24 |
+
import torch.nn as nn
|
| 25 |
+
|
| 26 |
+
from ... import initialization as init
|
| 27 |
+
from ...cache_utils import Cache
|
| 28 |
+
from ...generation import GenerationMixin
|
| 29 |
+
from ...modeling_outputs import BaseModelOutputWithPooling, ModelOutput
|
| 30 |
+
from ...modeling_utils import PreTrainedModel
|
| 31 |
+
from ...processing_utils import Unpack
|
| 32 |
+
from ...utils import TransformersKwargs, auto_docstring, can_return_tuple, torch_compilable_check
|
| 33 |
+
from ..auto import AutoModel
|
| 34 |
+
from .configuration_deepseek_vl_hybrid import DeepseekVLHybridConfig
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
@dataclass
|
| 38 |
+
@auto_docstring
|
| 39 |
+
class BaseModelOutputWithHighResVisionEncodings(BaseModelOutputWithPooling):
|
| 40 |
+
r"""
|
| 41 |
+
high_res_vision_last_hidden_state (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 42 |
+
Sequence of hidden-states at the output of the last layer of the high resolution vision model.
|
| 43 |
+
high_res_vision_hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
|
| 44 |
+
Tuple of `torch.FloatTensor` (one for the output of the embeddings, if the high resolution vision model has an embedding layer, +
|
| 45 |
+
one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.
|
| 46 |
+
|
| 47 |
+
Hidden-states of the high resolution vision model at the output of each layer plus the optional initial embedding outputs.
|
| 48 |
+
high_res_vision_attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
|
| 49 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 50 |
+
sequence_length)` from the high resolution vision model.
|
| 51 |
+
|
| 52 |
+
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
| 53 |
+
heads.
|
| 54 |
+
"""
|
| 55 |
+
|
| 56 |
+
high_res_vision_last_hidden_state: torch.FloatTensor | None = None
|
| 57 |
+
high_res_vision_hidden_states: tuple[torch.FloatTensor] | None = None
|
| 58 |
+
high_res_vision_attentions: tuple[torch.FloatTensor] | None = None
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
@dataclass
|
| 62 |
+
@auto_docstring(
|
| 63 |
+
custom_intro="""
|
| 64 |
+
Base class for DeepseekVLHybrid model's outputs that may also contain a past key/values (to speed up sequential decoding).
|
| 65 |
+
"""
|
| 66 |
+
)
|
| 67 |
+
class DeepseekVLHybridBaseModelOutputWithPast(ModelOutput):
|
| 68 |
+
r"""
|
| 69 |
+
last_hidden_state (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 70 |
+
Sequence of hidden-states at the output of the last layer of the model.
|
| 71 |
+
|
| 72 |
+
If `past_key_values` is used only the last hidden-state of the sequences of shape `(batch_size, 1,
|
| 73 |
+
hidden_size)` is output.
|
| 74 |
+
past_key_values (`Cache`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
|
| 75 |
+
It is a [`~cache_utils.Cache`] instance. For more details, see our [kv cache guide](https://huggingface.co/docs/transformers/en/kv_cache).
|
| 76 |
+
|
| 77 |
+
Contains pre-computed hidden-states (key and values in the self-attention blocks and optionally if
|
| 78 |
+
`config.is_encoder_decoder=True` in the cross-attention blocks) that can be used (see `past_key_values`
|
| 79 |
+
input) to speed up sequential decoding.
|
| 80 |
+
image_hidden_states (`tuple(torch.FloatTensor)`, *optional*):
|
| 81 |
+
Tuple of `torch.FloatTensor` (one for the output of the image embeddings, `(batch_size, num_images,
|
| 82 |
+
sequence_length, hidden_size)`.
|
| 83 |
+
|
| 84 |
+
image_hidden_states of the model produced by the vision encoder, and optionally by the perceiver
|
| 85 |
+
"""
|
| 86 |
+
|
| 87 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 88 |
+
past_key_values: Cache | None = None
|
| 89 |
+
hidden_states: tuple[torch.FloatTensor] | None = None
|
| 90 |
+
attentions: tuple[torch.FloatTensor] | None = None
|
| 91 |
+
image_hidden_states: tuple[torch.FloatTensor] | None = None
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
@dataclass
|
| 95 |
+
@auto_docstring(
|
| 96 |
+
custom_intro="""
|
| 97 |
+
Base class for DeepseekVLHybrid causal language model (or autoregressive) outputs.
|
| 98 |
+
"""
|
| 99 |
+
)
|
| 100 |
+
class DeepseekVLHybridCausalLMOutputWithPast(ModelOutput):
|
| 101 |
+
r"""
|
| 102 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` is provided):
|
| 103 |
+
Language modeling loss (for next-token prediction).
|
| 104 |
+
logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.vocab_size)`):
|
| 105 |
+
Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
|
| 106 |
+
past_key_values (`Cache`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
|
| 107 |
+
It is a [`~cache_utils.Cache`] instance. For more details, see our [kv cache guide](https://huggingface.co/docs/transformers/en/kv_cache).
|
| 108 |
+
|
| 109 |
+
Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see
|
| 110 |
+
`past_key_values` input) to speed up sequential decoding.
|
| 111 |
+
image_hidden_states (`tuple(torch.FloatTensor)`, *optional*):
|
| 112 |
+
Tuple of `torch.FloatTensor` (one for the output of the image embeddings, `(batch_size, num_images,
|
| 113 |
+
sequence_length, hidden_size)`.
|
| 114 |
+
|
| 115 |
+
image_hidden_states of the model produced by the vision encoder, and optionally by the perceiver
|
| 116 |
+
"""
|
| 117 |
+
|
| 118 |
+
loss: torch.FloatTensor | None = None
|
| 119 |
+
logits: torch.FloatTensor | None = None
|
| 120 |
+
past_key_values: Cache | None = None
|
| 121 |
+
hidden_states: tuple[torch.FloatTensor] | None = None
|
| 122 |
+
attentions: tuple[torch.FloatTensor] | None = None
|
| 123 |
+
image_hidden_states: tuple[torch.FloatTensor] | None = None
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
class DeepseekVLHybridLayerNorm(nn.LayerNorm):
|
| 127 |
+
r"""LayerNorm that supports two data formats: channels_last (default) or channels_first.
|
| 128 |
+
The ordering of the dimensions in the inputs. channels_last corresponds to inputs with shape (batch_size, height,
|
| 129 |
+
width, channels) while channels_first corresponds to inputs with shape (batch_size, channels, height, width).
|
| 130 |
+
"""
|
| 131 |
+
|
| 132 |
+
def __init__(self, normalized_shape, *, eps=1e-6, data_format="channels_last", **kwargs):
|
| 133 |
+
super().__init__(normalized_shape, eps=eps, **kwargs)
|
| 134 |
+
if data_format not in ["channels_last", "channels_first"]:
|
| 135 |
+
raise NotImplementedError(f"Unsupported data format: {data_format}")
|
| 136 |
+
self.data_format = data_format
|
| 137 |
+
|
| 138 |
+
def forward(self, features: torch.Tensor) -> torch.Tensor:
|
| 139 |
+
"""
|
| 140 |
+
Args:
|
| 141 |
+
features: Tensor of shape (batch_size, channels, height, width) OR (batch_size, height, width, channels)
|
| 142 |
+
"""
|
| 143 |
+
if self.data_format == "channels_first":
|
| 144 |
+
features = features.permute(0, 2, 3, 1)
|
| 145 |
+
features = super().forward(features)
|
| 146 |
+
features = features.permute(0, 3, 1, 2)
|
| 147 |
+
else:
|
| 148 |
+
features = super().forward(features)
|
| 149 |
+
return features
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
class DeepseekVLSamVisionNeck(nn.Module):
|
| 153 |
+
def __init__(self, config):
|
| 154 |
+
super().__init__()
|
| 155 |
+
self.config = config
|
| 156 |
+
|
| 157 |
+
self.conv1 = nn.Conv2d(config.hidden_size, config.output_channels, kernel_size=1, bias=False)
|
| 158 |
+
self.layer_norm1 = DeepseekVLHybridLayerNorm(config.output_channels, data_format="channels_first")
|
| 159 |
+
self.conv2 = nn.Conv2d(config.output_channels, config.output_channels, kernel_size=3, padding=1, bias=False)
|
| 160 |
+
self.layer_norm2 = DeepseekVLHybridLayerNorm(config.output_channels, data_format="channels_first")
|
| 161 |
+
|
| 162 |
+
def forward(self, hidden_states):
|
| 163 |
+
hidden_states = hidden_states.permute(0, 3, 1, 2)
|
| 164 |
+
hidden_states = self.conv1(hidden_states)
|
| 165 |
+
hidden_states = self.layer_norm1(hidden_states)
|
| 166 |
+
|
| 167 |
+
hidden_states = self.conv2(hidden_states)
|
| 168 |
+
hidden_states = self.layer_norm2(hidden_states)
|
| 169 |
+
return hidden_states
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
class DeepseekVLSamVisionProj(nn.Module):
|
| 173 |
+
def __init__(self, config, output_size: int = 24):
|
| 174 |
+
super().__init__()
|
| 175 |
+
self.config = config
|
| 176 |
+
self.output_size = output_size
|
| 177 |
+
|
| 178 |
+
self.conv1 = nn.Conv2d(
|
| 179 |
+
config.output_channels, config.output_channels * 2, kernel_size=3, stride=2, padding=1, bias=False
|
| 180 |
+
)
|
| 181 |
+
self.conv2 = nn.Conv2d(
|
| 182 |
+
config.output_channels * 2, config.output_channels * 4, kernel_size=3, stride=2, padding=1, bias=False
|
| 183 |
+
)
|
| 184 |
+
|
| 185 |
+
def forward(self, features: torch.Tensor) -> torch.Tensor:
|
| 186 |
+
# interpolate Sam encodings to match Siglip encodings
|
| 187 |
+
features = torch.nn.functional.interpolate(
|
| 188 |
+
features,
|
| 189 |
+
size=(4 * self.output_size, 4 * self.output_size),
|
| 190 |
+
mode="bilinear",
|
| 191 |
+
align_corners=False,
|
| 192 |
+
)
|
| 193 |
+
features = self.conv1(features)
|
| 194 |
+
features = self.conv2(features)
|
| 195 |
+
return features
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
class DeepseekVLHybridAligner(nn.Module):
|
| 199 |
+
def __init__(self, config: DeepseekVLHybridConfig):
|
| 200 |
+
super().__init__()
|
| 201 |
+
|
| 202 |
+
in_channels = config.vision_config.hidden_size
|
| 203 |
+
high_res_in_channels = config.high_res_vision_config.output_channels * 4
|
| 204 |
+
out_channels = config.text_config.hidden_size
|
| 205 |
+
|
| 206 |
+
self.vision_proj = nn.Linear(in_channels, out_channels // 2)
|
| 207 |
+
self.high_res_vision_proj = nn.Linear(high_res_in_channels, out_channels // 2)
|
| 208 |
+
|
| 209 |
+
self.act = nn.GELU()
|
| 210 |
+
self.proj = nn.Linear(out_channels, out_channels)
|
| 211 |
+
|
| 212 |
+
def forward(
|
| 213 |
+
self,
|
| 214 |
+
vision_encodings: torch.Tensor,
|
| 215 |
+
high_res_vision_encodings: torch.Tensor,
|
| 216 |
+
) -> torch.Tensor:
|
| 217 |
+
vision_encodings = self.vision_proj(vision_encodings)
|
| 218 |
+
high_res_vision_encodings = self.high_res_vision_proj(high_res_vision_encodings)
|
| 219 |
+
|
| 220 |
+
encodings = torch.concat([high_res_vision_encodings, vision_encodings], dim=-1)
|
| 221 |
+
encodings = self.act(encodings)
|
| 222 |
+
encodings = self.proj(encodings)
|
| 223 |
+
|
| 224 |
+
return encodings
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
@auto_docstring
|
| 228 |
+
class DeepseekVLHybridPreTrainedModel(PreTrainedModel):
|
| 229 |
+
config: DeepseekVLHybridConfig
|
| 230 |
+
base_model_prefix = "model"
|
| 231 |
+
input_modalities = ("image", "text")
|
| 232 |
+
supports_gradient_checkpointing = True
|
| 233 |
+
_no_split_modules = ["LlamaDecoderLayer"]
|
| 234 |
+
_skip_keys_device_placement = ["past_key_values", "causal_mask"]
|
| 235 |
+
_supports_flash_attn = True
|
| 236 |
+
_supports_sdpa = True
|
| 237 |
+
|
| 238 |
+
_can_compile_fullgraph = True
|
| 239 |
+
|
| 240 |
+
@torch.no_grad()
|
| 241 |
+
def _init_weights(self, module):
|
| 242 |
+
"""Initialize the weights"""
|
| 243 |
+
if isinstance(module, nn.Linear):
|
| 244 |
+
init.normal_(module.weight, mean=0.0, std=self.config.text_config.initializer_range)
|
| 245 |
+
if module.bias is not None:
|
| 246 |
+
init.zeros_(module.bias)
|
| 247 |
+
elif isinstance(module, nn.Conv2d):
|
| 248 |
+
init.kaiming_normal_(module.weight, mode="fan_out", nonlinearity="relu")
|
| 249 |
+
if module.bias is not None:
|
| 250 |
+
init.zeros_(module.bias)
|
| 251 |
+
elif isinstance(module, DeepseekVLHybridLayerNorm):
|
| 252 |
+
init.ones_(module.weight)
|
| 253 |
+
init.zeros_(module.bias)
|
| 254 |
+
elif isinstance(module, DeepseekVLHybridModel):
|
| 255 |
+
init.zeros_(module.high_res_vision_alpha)
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
DEEPSEEK_VL_COMMON_CUSTOM_ARGS = r"""
|
| 259 |
+
high_res_pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size), *optional*):
|
| 260 |
+
The tensors corresponding to the input images. Pixel values can be obtained using
|
| 261 |
+
[`AutoImageProcessor`].
|
| 262 |
+
"""
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
@auto_docstring
|
| 266 |
+
class DeepseekVLHybridModel(DeepseekVLHybridPreTrainedModel):
|
| 267 |
+
def __init__(self, config):
|
| 268 |
+
super().__init__(config)
|
| 269 |
+
self.output_size = config.vision_config.image_size // config.vision_config.patch_size
|
| 270 |
+
self.global_attn_index = config.high_res_vision_config.global_attn_indexes[0]
|
| 271 |
+
|
| 272 |
+
self.high_res_vision_model = AutoModel.from_config(config.high_res_vision_config)
|
| 273 |
+
self.high_res_vision_neck = DeepseekVLSamVisionNeck(config.high_res_vision_config)
|
| 274 |
+
self.high_res_vision_proj = DeepseekVLSamVisionProj(
|
| 275 |
+
config.high_res_vision_config, output_size=self.output_size
|
| 276 |
+
)
|
| 277 |
+
self.high_res_vision_alpha = nn.Parameter(torch.zeros(1))
|
| 278 |
+
self.config = config
|
| 279 |
+
|
| 280 |
+
self.vision_model = AutoModel.from_config(config.vision_config)
|
| 281 |
+
self.aligner = DeepseekVLHybridAligner(config)
|
| 282 |
+
|
| 283 |
+
self.language_model = AutoModel.from_config(config=config.text_config)
|
| 284 |
+
|
| 285 |
+
self.gradient_checkpointing = False
|
| 286 |
+
# Initialize weights and apply final processing.
|
| 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 |
+
@can_return_tuple
|
| 296 |
+
@auto_docstring(custom_args=DEEPSEEK_VL_COMMON_CUSTOM_ARGS)
|
| 297 |
+
def get_image_features(
|
| 298 |
+
self,
|
| 299 |
+
pixel_values: torch.FloatTensor,
|
| 300 |
+
high_res_pixel_values: torch.FloatTensor,
|
| 301 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 302 |
+
) -> tuple | BaseModelOutputWithHighResVisionEncodings:
|
| 303 |
+
low_res_outputs = self.get_low_res_image_features(pixel_values, **kwargs)
|
| 304 |
+
high_res_outputs = self.get_high_res_image_features(high_res_pixel_values, **kwargs)
|
| 305 |
+
image_features = self.aligner(low_res_outputs.last_hidden_state, high_res_outputs.last_hidden_state)
|
| 306 |
+
|
| 307 |
+
return BaseModelOutputWithHighResVisionEncodings(
|
| 308 |
+
last_hidden_state=low_res_outputs.last_hidden_state,
|
| 309 |
+
pooler_output=image_features,
|
| 310 |
+
hidden_states=low_res_outputs.hidden_states,
|
| 311 |
+
attentions=low_res_outputs.attentions,
|
| 312 |
+
high_res_vision_last_hidden_state=high_res_outputs.last_hidden_state,
|
| 313 |
+
high_res_vision_hidden_states=high_res_outputs.hidden_states,
|
| 314 |
+
high_res_vision_attentions=high_res_outputs.attentions,
|
| 315 |
+
)
|
| 316 |
+
|
| 317 |
+
def get_placeholder_mask(
|
| 318 |
+
self, input_ids: torch.LongTensor, inputs_embeds: torch.FloatTensor, image_features: torch.FloatTensor
|
| 319 |
+
):
|
| 320 |
+
"""
|
| 321 |
+
Obtains multimodal placeholder mask from `input_ids` or `inputs_embeds`, and checks that the placeholder token count is
|
| 322 |
+
equal to the length of multimodal features. If the lengths are different, an error is raised.
|
| 323 |
+
"""
|
| 324 |
+
if input_ids is None:
|
| 325 |
+
special_image_mask = inputs_embeds == self.get_input_embeddings()(
|
| 326 |
+
torch.tensor(self.config.image_token_id, dtype=torch.long, device=inputs_embeds.device)
|
| 327 |
+
)
|
| 328 |
+
special_image_mask = special_image_mask.all(-1)
|
| 329 |
+
else:
|
| 330 |
+
special_image_mask = input_ids == self.config.image_token_id
|
| 331 |
+
|
| 332 |
+
n_image_tokens = special_image_mask.sum()
|
| 333 |
+
n_image_features = image_features.shape[0] * image_features.shape[1]
|
| 334 |
+
special_image_mask = special_image_mask.unsqueeze(-1).expand_as(inputs_embeds).to(inputs_embeds.device)
|
| 335 |
+
torch_compilable_check(
|
| 336 |
+
inputs_embeds[special_image_mask].numel() == image_features.numel(),
|
| 337 |
+
f"Image features and image tokens do not match, tokens: {n_image_tokens}, features: {n_image_features}",
|
| 338 |
+
)
|
| 339 |
+
return special_image_mask
|
| 340 |
+
|
| 341 |
+
@can_return_tuple
|
| 342 |
+
@auto_docstring(custom_args=DEEPSEEK_VL_COMMON_CUSTOM_ARGS)
|
| 343 |
+
def forward(
|
| 344 |
+
self,
|
| 345 |
+
input_ids: torch.LongTensor | None = None,
|
| 346 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 347 |
+
high_res_pixel_values: torch.FloatTensor | None = None,
|
| 348 |
+
attention_mask: torch.Tensor | None = None,
|
| 349 |
+
position_ids: torch.LongTensor | None = None,
|
| 350 |
+
past_key_values: Cache | None = None,
|
| 351 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 352 |
+
use_cache: bool | None = None,
|
| 353 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 354 |
+
**kwargs,
|
| 355 |
+
) -> DeepseekVLHybridBaseModelOutputWithPast:
|
| 356 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 357 |
+
raise ValueError(
|
| 358 |
+
"You cannot specify both input_ids and inputs_embeds at the same time, and must specify either one"
|
| 359 |
+
)
|
| 360 |
+
|
| 361 |
+
if pixel_values is not None and high_res_pixel_values is None:
|
| 362 |
+
raise ValueError("Both pixel_values and high_res_pixel_values should be specified at the same time")
|
| 363 |
+
|
| 364 |
+
if inputs_embeds is None:
|
| 365 |
+
inputs_embeds = self.get_input_embeddings()(input_ids)
|
| 366 |
+
|
| 367 |
+
if pixel_values is not None:
|
| 368 |
+
if input_ids is None:
|
| 369 |
+
image_attention_mask = inputs_embeds == self.get_input_embeddings()(
|
| 370 |
+
torch.tensor(self.config.image_token_id, dtype=torch.long, device=inputs_embeds.device)
|
| 371 |
+
)
|
| 372 |
+
image_attention_mask = image_attention_mask.all(-1)
|
| 373 |
+
else:
|
| 374 |
+
image_attention_mask = input_ids == self.config.image_token_id
|
| 375 |
+
|
| 376 |
+
image_attention_mask = image_attention_mask.unsqueeze(-1).expand_as(inputs_embeds).to(inputs_embeds.device)
|
| 377 |
+
image_embeds = self.get_image_features(pixel_values, high_res_pixel_values, return_dict=True).pooler_output
|
| 378 |
+
image_features = image_embeds.reshape(-1, inputs_embeds.shape[-1])
|
| 379 |
+
image_features = image_features.to(inputs_embeds.device, inputs_embeds.dtype)
|
| 380 |
+
inputs_embeds = inputs_embeds.masked_scatter(image_attention_mask, image_features)
|
| 381 |
+
|
| 382 |
+
lm_output = self.language_model(
|
| 383 |
+
inputs_embeds=inputs_embeds,
|
| 384 |
+
attention_mask=attention_mask,
|
| 385 |
+
position_ids=position_ids,
|
| 386 |
+
past_key_values=past_key_values,
|
| 387 |
+
use_cache=use_cache,
|
| 388 |
+
logits_to_keep=logits_to_keep,
|
| 389 |
+
**kwargs,
|
| 390 |
+
)
|
| 391 |
+
|
| 392 |
+
return DeepseekVLHybridBaseModelOutputWithPast(
|
| 393 |
+
last_hidden_state=lm_output.last_hidden_state,
|
| 394 |
+
past_key_values=lm_output.past_key_values,
|
| 395 |
+
hidden_states=lm_output.hidden_states,
|
| 396 |
+
attentions=lm_output.attentions,
|
| 397 |
+
image_hidden_states=image_embeds if pixel_values is not None else None,
|
| 398 |
+
)
|
| 399 |
+
|
| 400 |
+
def get_low_res_image_features(self, pixel_values: torch.FloatTensor, **kwargs: Unpack[TransformersKwargs]):
|
| 401 |
+
return self.vision_model(pixel_values, return_dict=True, **kwargs)
|
| 402 |
+
|
| 403 |
+
def get_high_res_image_features(
|
| 404 |
+
self,
|
| 405 |
+
pixel_values: torch.FloatTensor,
|
| 406 |
+
output_hidden_states: bool | None = None,
|
| 407 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 408 |
+
):
|
| 409 |
+
high_res_outputs = self.high_res_vision_model(
|
| 410 |
+
pixel_values=pixel_values,
|
| 411 |
+
output_hidden_states=True, # Ignore arg on purpose
|
| 412 |
+
return_dict=True,
|
| 413 |
+
**kwargs,
|
| 414 |
+
)
|
| 415 |
+
last_hidden_state = high_res_outputs.last_hidden_state
|
| 416 |
+
last_hidden_state = self.high_res_vision_proj(last_hidden_state)
|
| 417 |
+
|
| 418 |
+
hidden_states = high_res_outputs.hidden_states
|
| 419 |
+
global_hidden_state = hidden_states[self.global_attn_index + 1] # +1 for embedding layer
|
| 420 |
+
global_hidden_state = self.high_res_vision_neck(global_hidden_state)
|
| 421 |
+
global_hidden_state = self.high_res_vision_proj(global_hidden_state)
|
| 422 |
+
|
| 423 |
+
output = last_hidden_state + global_hidden_state * self.high_res_vision_alpha
|
| 424 |
+
|
| 425 |
+
# batch_size, hidden_size, height, width -> batch_size, seq_len, hidden_size
|
| 426 |
+
output = output.permute(0, 2, 3, 1)
|
| 427 |
+
output = output.reshape(output.shape[0], -1, output.shape[-1])
|
| 428 |
+
high_res_outputs.last_hidden_state = output
|
| 429 |
+
|
| 430 |
+
return high_res_outputs
|
| 431 |
+
|
| 432 |
+
|
| 433 |
+
class DeepseekVLHybridForConditionalGeneration(DeepseekVLHybridPreTrainedModel, GenerationMixin):
|
| 434 |
+
_tied_weights_keys = {"lm_head.weight": "model.language_model.embed_tokens.weight"}
|
| 435 |
+
output_modalities = ("text",)
|
| 436 |
+
_can_compile_fullgraph = True
|
| 437 |
+
|
| 438 |
+
def __init__(self, config: DeepseekVLHybridConfig):
|
| 439 |
+
super().__init__(config)
|
| 440 |
+
self.config = config
|
| 441 |
+
self.model = DeepseekVLHybridModel(config)
|
| 442 |
+
self.lm_head = nn.Linear(config.text_config.hidden_size, config.text_config.vocab_size, bias=False)
|
| 443 |
+
|
| 444 |
+
# Initialize weights and apply final processing.
|
| 445 |
+
self.post_init()
|
| 446 |
+
|
| 447 |
+
def get_input_embeddings(self):
|
| 448 |
+
return self.model.language_model.get_input_embeddings()
|
| 449 |
+
|
| 450 |
+
def set_input_embeddings(self, value):
|
| 451 |
+
self.model.language_model.set_input_embeddings(value)
|
| 452 |
+
|
| 453 |
+
@can_return_tuple
|
| 454 |
+
@auto_docstring(custom_args=DEEPSEEK_VL_COMMON_CUSTOM_ARGS)
|
| 455 |
+
def forward(
|
| 456 |
+
self,
|
| 457 |
+
input_ids: torch.LongTensor | None = None,
|
| 458 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 459 |
+
high_res_pixel_values: torch.FloatTensor | None = None,
|
| 460 |
+
attention_mask: torch.Tensor | None = None,
|
| 461 |
+
position_ids: torch.LongTensor | None = None,
|
| 462 |
+
past_key_values: Cache | None = None,
|
| 463 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 464 |
+
labels: torch.LongTensor | None = None,
|
| 465 |
+
use_cache: bool | None = None,
|
| 466 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 467 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 468 |
+
) -> DeepseekVLHybridCausalLMOutputWithPast:
|
| 469 |
+
r"""
|
| 470 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 471 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 472 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 473 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 474 |
+
"""
|
| 475 |
+
outputs = self.model(
|
| 476 |
+
input_ids=input_ids,
|
| 477 |
+
pixel_values=pixel_values,
|
| 478 |
+
high_res_pixel_values=high_res_pixel_values,
|
| 479 |
+
attention_mask=attention_mask,
|
| 480 |
+
position_ids=position_ids,
|
| 481 |
+
past_key_values=past_key_values,
|
| 482 |
+
inputs_embeds=inputs_embeds,
|
| 483 |
+
use_cache=use_cache,
|
| 484 |
+
**kwargs,
|
| 485 |
+
)
|
| 486 |
+
hidden_states = outputs.last_hidden_state
|
| 487 |
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
| 488 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 489 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
| 490 |
+
|
| 491 |
+
loss = None
|
| 492 |
+
if labels is not None:
|
| 493 |
+
loss = self.loss_function(
|
| 494 |
+
logits=logits, labels=labels, vocab_size=self.config.text_config.vocab_size, **kwargs
|
| 495 |
+
)
|
| 496 |
+
|
| 497 |
+
return DeepseekVLHybridCausalLMOutputWithPast(
|
| 498 |
+
loss=loss,
|
| 499 |
+
logits=logits,
|
| 500 |
+
past_key_values=outputs.past_key_values,
|
| 501 |
+
hidden_states=outputs.hidden_states,
|
| 502 |
+
attentions=outputs.attentions,
|
| 503 |
+
image_hidden_states=outputs.image_hidden_states,
|
| 504 |
+
)
|
| 505 |
+
|
| 506 |
+
def prepare_inputs_for_generation(
|
| 507 |
+
self,
|
| 508 |
+
input_ids,
|
| 509 |
+
past_key_values=None,
|
| 510 |
+
inputs_embeds=None,
|
| 511 |
+
pixel_values=None,
|
| 512 |
+
high_res_pixel_values=None,
|
| 513 |
+
attention_mask=None,
|
| 514 |
+
logits_to_keep=None,
|
| 515 |
+
is_first_iteration=False,
|
| 516 |
+
**kwargs,
|
| 517 |
+
):
|
| 518 |
+
model_inputs = super().prepare_inputs_for_generation(
|
| 519 |
+
input_ids,
|
| 520 |
+
past_key_values=past_key_values,
|
| 521 |
+
inputs_embeds=inputs_embeds,
|
| 522 |
+
attention_mask=attention_mask,
|
| 523 |
+
logits_to_keep=logits_to_keep,
|
| 524 |
+
is_first_iteration=is_first_iteration,
|
| 525 |
+
**kwargs,
|
| 526 |
+
)
|
| 527 |
+
|
| 528 |
+
if is_first_iteration or not kwargs.get("use_cache", True):
|
| 529 |
+
# Pixel values are used only in the first iteration if available
|
| 530 |
+
# In subsequent iterations, they are already merged with text and cached
|
| 531 |
+
# NOTE: first iteration doesn't have to be prefill, it can be the first
|
| 532 |
+
# iteration with a question and cached system prompt (continue generate from cache)
|
| 533 |
+
model_inputs["pixel_values"] = pixel_values
|
| 534 |
+
model_inputs["high_res_pixel_values"] = high_res_pixel_values
|
| 535 |
+
|
| 536 |
+
return model_inputs
|
| 537 |
+
|
| 538 |
+
|
| 539 |
+
__all__ = ["DeepseekVLHybridPreTrainedModel", "DeepseekVLHybridModel", "DeepseekVLHybridForConditionalGeneration"]
|
third_party/transformers/src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.py
ADDED
|
@@ -0,0 +1,787 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 Deepseek AI and The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from collections.abc import Iterable
|
| 16 |
+
from dataclasses import dataclass
|
| 17 |
+
from typing import Union
|
| 18 |
+
|
| 19 |
+
import numpy as np
|
| 20 |
+
import torch
|
| 21 |
+
import torch.nn as nn
|
| 22 |
+
from huggingface_hub.dataclasses import strict
|
| 23 |
+
|
| 24 |
+
from ... import initialization as init
|
| 25 |
+
from ...cache_utils import Cache
|
| 26 |
+
from ...configuration_utils import PreTrainedConfig
|
| 27 |
+
from ...image_processing_backends import PilBackend, TorchvisionBackend
|
| 28 |
+
from ...image_processing_utils import BatchFeature, get_size_dict
|
| 29 |
+
from ...image_transforms import group_images_by_shape, reorder_images
|
| 30 |
+
from ...image_utils import (
|
| 31 |
+
OPENAI_CLIP_MEAN,
|
| 32 |
+
OPENAI_CLIP_STD,
|
| 33 |
+
ImageInput,
|
| 34 |
+
PILImageResampling,
|
| 35 |
+
SizeDict,
|
| 36 |
+
)
|
| 37 |
+
from ...modeling_outputs import BaseModelOutputWithPooling
|
| 38 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 39 |
+
from ...tokenization_utils_base import (
|
| 40 |
+
PreTokenizedInput,
|
| 41 |
+
TextInput,
|
| 42 |
+
)
|
| 43 |
+
from ...utils import (
|
| 44 |
+
TensorType,
|
| 45 |
+
TransformersKwargs,
|
| 46 |
+
auto_docstring,
|
| 47 |
+
can_return_tuple,
|
| 48 |
+
logging,
|
| 49 |
+
)
|
| 50 |
+
from ..auto import CONFIG_MAPPING, AutoConfig, AutoModel
|
| 51 |
+
from ..deepseek_vl.configuration_deepseek_vl import DeepseekVLConfig
|
| 52 |
+
from ..deepseek_vl.image_processing_deepseek_vl import DeepseekVLImageProcessor
|
| 53 |
+
from ..deepseek_vl.image_processing_pil_deepseek_vl import DeepseekVLImageProcessorPil
|
| 54 |
+
from ..deepseek_vl.modeling_deepseek_vl import (
|
| 55 |
+
DeepseekVLForConditionalGeneration,
|
| 56 |
+
DeepseekVLModel,
|
| 57 |
+
DeepseekVLPreTrainedModel,
|
| 58 |
+
)
|
| 59 |
+
from ..deepseek_vl.processing_deepseek_vl import DeepseekVLProcessor, DeepseekVLProcessorKwargs
|
| 60 |
+
from ..idefics.modeling_idefics import IdeficsBaseModelOutputWithPast, IdeficsCausalLMOutputWithPast
|
| 61 |
+
from ..sam.modeling_sam import SamLayerNorm, SamVisionNeck
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
logger = logging.get_logger(__name__)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
DEEPSEEK_VL_COMMON_CUSTOM_ARGS = r"""
|
| 68 |
+
high_res_pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size), *optional*):
|
| 69 |
+
The tensors corresponding to the input images. Pixel values can be obtained using
|
| 70 |
+
[`AutoImageProcessor`].
|
| 71 |
+
"""
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
@auto_docstring(checkpoint="deepseek-community/deepseek-vl-7b-chat")
|
| 75 |
+
@strict
|
| 76 |
+
class DeepseekVLHybridConfig(DeepseekVLConfig):
|
| 77 |
+
r"""
|
| 78 |
+
high_res_vision_config (`Union[AutoConfig, dict]`, *optional*, defaults to `SamVisionConfig`):
|
| 79 |
+
The config object or dictionary of the high resolution vision backbone.
|
| 80 |
+
|
| 81 |
+
Example:
|
| 82 |
+
|
| 83 |
+
```python
|
| 84 |
+
>>> from transformers import DeepseekVLHybridConfig, DeepseekVLHybridModel
|
| 85 |
+
|
| 86 |
+
>>> # Initializing a DeepseekVLHybrid deepseek-community/deepseek-vl-7b-chat style configuration
|
| 87 |
+
>>> configuration = DeepseekVLHybridConfig()
|
| 88 |
+
|
| 89 |
+
>>> # Initializing a model (with random weights) from the deepseek-community/deepseek-vl-7b-chat style configuration
|
| 90 |
+
>>> model = DeepseekVLHybridModel(configuration)
|
| 91 |
+
|
| 92 |
+
>>> # Accessing the model configuration
|
| 93 |
+
>>> configuration = model.config
|
| 94 |
+
```"""
|
| 95 |
+
|
| 96 |
+
model_type = "deepseek_vl_hybrid"
|
| 97 |
+
sub_configs = {"text_config": AutoConfig, "vision_config": AutoConfig, "high_res_vision_config": AutoConfig}
|
| 98 |
+
|
| 99 |
+
high_res_vision_config: dict | PreTrainedConfig | None = None
|
| 100 |
+
|
| 101 |
+
def __post_init__(self, **kwargs):
|
| 102 |
+
if self.high_res_vision_config is None:
|
| 103 |
+
self.high_res_vision_config = {}
|
| 104 |
+
logger.info("`high_res_vision_config` is `None`. Initializing the `SamVisionConfig` with default values.")
|
| 105 |
+
|
| 106 |
+
if isinstance(self.high_res_vision_config, dict):
|
| 107 |
+
self.high_res_vision_config["model_type"] = self.high_res_vision_config.get(
|
| 108 |
+
"model_type", "sam_vision_model"
|
| 109 |
+
)
|
| 110 |
+
self.high_res_vision_config = CONFIG_MAPPING[self.high_res_vision_config["model_type"]](
|
| 111 |
+
**self.high_res_vision_config
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
super().__post_init__(**kwargs)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
@dataclass
|
| 118 |
+
@auto_docstring
|
| 119 |
+
class BaseModelOutputWithHighResVisionEncodings(BaseModelOutputWithPooling):
|
| 120 |
+
r"""
|
| 121 |
+
high_res_vision_last_hidden_state (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 122 |
+
Sequence of hidden-states at the output of the last layer of the high resolution vision model.
|
| 123 |
+
high_res_vision_hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
|
| 124 |
+
Tuple of `torch.FloatTensor` (one for the output of the embeddings, if the high resolution vision model has an embedding layer, +
|
| 125 |
+
one for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.
|
| 126 |
+
|
| 127 |
+
Hidden-states of the high resolution vision model at the output of each layer plus the optional initial embedding outputs.
|
| 128 |
+
high_res_vision_attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
|
| 129 |
+
Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
|
| 130 |
+
sequence_length)` from the high resolution vision model.
|
| 131 |
+
|
| 132 |
+
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
| 133 |
+
heads.
|
| 134 |
+
"""
|
| 135 |
+
|
| 136 |
+
high_res_vision_last_hidden_state: torch.FloatTensor | None = None
|
| 137 |
+
high_res_vision_hidden_states: tuple[torch.FloatTensor] | None = None
|
| 138 |
+
high_res_vision_attentions: tuple[torch.FloatTensor] | None = None
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
class DeepseekVLHybridBaseModelOutputWithPast(IdeficsBaseModelOutputWithPast):
|
| 142 |
+
pass
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
class DeepseekVLHybridCausalLMOutputWithPast(IdeficsCausalLMOutputWithPast):
|
| 146 |
+
pass
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
class DeepseekVLHybridLayerNorm(SamLayerNorm):
|
| 150 |
+
pass
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
class DeepseekVLSamVisionNeck(SamVisionNeck):
|
| 154 |
+
def __init__(self, config):
|
| 155 |
+
super().__init__(config)
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
class DeepseekVLSamVisionProj(nn.Module):
|
| 159 |
+
def __init__(self, config, output_size: int = 24):
|
| 160 |
+
super().__init__()
|
| 161 |
+
self.config = config
|
| 162 |
+
self.output_size = output_size
|
| 163 |
+
|
| 164 |
+
self.conv1 = nn.Conv2d(
|
| 165 |
+
config.output_channels, config.output_channels * 2, kernel_size=3, stride=2, padding=1, bias=False
|
| 166 |
+
)
|
| 167 |
+
self.conv2 = nn.Conv2d(
|
| 168 |
+
config.output_channels * 2, config.output_channels * 4, kernel_size=3, stride=2, padding=1, bias=False
|
| 169 |
+
)
|
| 170 |
+
|
| 171 |
+
def forward(self, features: torch.Tensor) -> torch.Tensor:
|
| 172 |
+
# interpolate Sam encodings to match Siglip encodings
|
| 173 |
+
features = torch.nn.functional.interpolate(
|
| 174 |
+
features,
|
| 175 |
+
size=(4 * self.output_size, 4 * self.output_size),
|
| 176 |
+
mode="bilinear",
|
| 177 |
+
align_corners=False,
|
| 178 |
+
)
|
| 179 |
+
features = self.conv1(features)
|
| 180 |
+
features = self.conv2(features)
|
| 181 |
+
return features
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
class DeepseekVLHybridAligner(nn.Module):
|
| 185 |
+
def __init__(self, config: DeepseekVLHybridConfig):
|
| 186 |
+
super().__init__()
|
| 187 |
+
|
| 188 |
+
in_channels = config.vision_config.hidden_size
|
| 189 |
+
high_res_in_channels = config.high_res_vision_config.output_channels * 4
|
| 190 |
+
out_channels = config.text_config.hidden_size
|
| 191 |
+
|
| 192 |
+
self.vision_proj = nn.Linear(in_channels, out_channels // 2)
|
| 193 |
+
self.high_res_vision_proj = nn.Linear(high_res_in_channels, out_channels // 2)
|
| 194 |
+
|
| 195 |
+
self.act = nn.GELU()
|
| 196 |
+
self.proj = nn.Linear(out_channels, out_channels)
|
| 197 |
+
|
| 198 |
+
def forward(
|
| 199 |
+
self,
|
| 200 |
+
vision_encodings: torch.Tensor,
|
| 201 |
+
high_res_vision_encodings: torch.Tensor,
|
| 202 |
+
) -> torch.Tensor:
|
| 203 |
+
vision_encodings = self.vision_proj(vision_encodings)
|
| 204 |
+
high_res_vision_encodings = self.high_res_vision_proj(high_res_vision_encodings)
|
| 205 |
+
|
| 206 |
+
encodings = torch.concat([high_res_vision_encodings, vision_encodings], dim=-1)
|
| 207 |
+
encodings = self.act(encodings)
|
| 208 |
+
encodings = self.proj(encodings)
|
| 209 |
+
|
| 210 |
+
return encodings
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
class DeepseekVLHybridPreTrainedModel(DeepseekVLPreTrainedModel):
|
| 214 |
+
@torch.no_grad()
|
| 215 |
+
def _init_weights(self, module):
|
| 216 |
+
"""Initialize the weights"""
|
| 217 |
+
if isinstance(module, nn.Linear):
|
| 218 |
+
init.normal_(module.weight, mean=0.0, std=self.config.text_config.initializer_range)
|
| 219 |
+
if module.bias is not None:
|
| 220 |
+
init.zeros_(module.bias)
|
| 221 |
+
elif isinstance(module, nn.Conv2d):
|
| 222 |
+
init.kaiming_normal_(module.weight, mode="fan_out", nonlinearity="relu")
|
| 223 |
+
if module.bias is not None:
|
| 224 |
+
init.zeros_(module.bias)
|
| 225 |
+
elif isinstance(module, DeepseekVLHybridLayerNorm):
|
| 226 |
+
init.ones_(module.weight)
|
| 227 |
+
init.zeros_(module.bias)
|
| 228 |
+
elif isinstance(module, DeepseekVLHybridModel):
|
| 229 |
+
init.zeros_(module.high_res_vision_alpha)
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
class DeepseekVLHybridModel(DeepseekVLModel):
|
| 233 |
+
def __init__(self, config):
|
| 234 |
+
self.output_size = config.vision_config.image_size // config.vision_config.patch_size
|
| 235 |
+
self.global_attn_index = config.high_res_vision_config.global_attn_indexes[0]
|
| 236 |
+
|
| 237 |
+
self.high_res_vision_model = AutoModel.from_config(config.high_res_vision_config)
|
| 238 |
+
self.high_res_vision_neck = DeepseekVLSamVisionNeck(config.high_res_vision_config)
|
| 239 |
+
self.high_res_vision_proj = DeepseekVLSamVisionProj(
|
| 240 |
+
config.high_res_vision_config, output_size=self.output_size
|
| 241 |
+
)
|
| 242 |
+
self.high_res_vision_alpha = nn.Parameter(torch.zeros(1))
|
| 243 |
+
|
| 244 |
+
super().__init__(config)
|
| 245 |
+
|
| 246 |
+
def get_low_res_image_features(self, pixel_values: torch.FloatTensor, **kwargs: Unpack[TransformersKwargs]):
|
| 247 |
+
return self.vision_model(pixel_values, return_dict=True, **kwargs)
|
| 248 |
+
|
| 249 |
+
def get_high_res_image_features(
|
| 250 |
+
self,
|
| 251 |
+
pixel_values: torch.FloatTensor,
|
| 252 |
+
output_hidden_states: bool | None = None,
|
| 253 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 254 |
+
):
|
| 255 |
+
high_res_outputs = self.high_res_vision_model(
|
| 256 |
+
pixel_values=pixel_values,
|
| 257 |
+
output_hidden_states=True, # Ignore arg on purpose
|
| 258 |
+
return_dict=True,
|
| 259 |
+
**kwargs,
|
| 260 |
+
)
|
| 261 |
+
last_hidden_state = high_res_outputs.last_hidden_state
|
| 262 |
+
last_hidden_state = self.high_res_vision_proj(last_hidden_state)
|
| 263 |
+
|
| 264 |
+
hidden_states = high_res_outputs.hidden_states
|
| 265 |
+
global_hidden_state = hidden_states[self.global_attn_index + 1] # +1 for embedding layer
|
| 266 |
+
global_hidden_state = self.high_res_vision_neck(global_hidden_state)
|
| 267 |
+
global_hidden_state = self.high_res_vision_proj(global_hidden_state)
|
| 268 |
+
|
| 269 |
+
output = last_hidden_state + global_hidden_state * self.high_res_vision_alpha
|
| 270 |
+
|
| 271 |
+
# batch_size, hidden_size, height, width -> batch_size, seq_len, hidden_size
|
| 272 |
+
output = output.permute(0, 2, 3, 1)
|
| 273 |
+
output = output.reshape(output.shape[0], -1, output.shape[-1])
|
| 274 |
+
high_res_outputs.last_hidden_state = output
|
| 275 |
+
|
| 276 |
+
return high_res_outputs
|
| 277 |
+
|
| 278 |
+
@can_return_tuple
|
| 279 |
+
@auto_docstring(custom_args=DEEPSEEK_VL_COMMON_CUSTOM_ARGS)
|
| 280 |
+
def get_image_features(
|
| 281 |
+
self,
|
| 282 |
+
pixel_values: torch.FloatTensor,
|
| 283 |
+
high_res_pixel_values: torch.FloatTensor,
|
| 284 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 285 |
+
) -> tuple | BaseModelOutputWithHighResVisionEncodings:
|
| 286 |
+
low_res_outputs = self.get_low_res_image_features(pixel_values, **kwargs)
|
| 287 |
+
high_res_outputs = self.get_high_res_image_features(high_res_pixel_values, **kwargs)
|
| 288 |
+
image_features = self.aligner(low_res_outputs.last_hidden_state, high_res_outputs.last_hidden_state)
|
| 289 |
+
|
| 290 |
+
return BaseModelOutputWithHighResVisionEncodings(
|
| 291 |
+
last_hidden_state=low_res_outputs.last_hidden_state,
|
| 292 |
+
pooler_output=image_features,
|
| 293 |
+
hidden_states=low_res_outputs.hidden_states,
|
| 294 |
+
attentions=low_res_outputs.attentions,
|
| 295 |
+
high_res_vision_last_hidden_state=high_res_outputs.last_hidden_state,
|
| 296 |
+
high_res_vision_hidden_states=high_res_outputs.hidden_states,
|
| 297 |
+
high_res_vision_attentions=high_res_outputs.attentions,
|
| 298 |
+
)
|
| 299 |
+
|
| 300 |
+
@can_return_tuple
|
| 301 |
+
@auto_docstring(custom_args=DEEPSEEK_VL_COMMON_CUSTOM_ARGS)
|
| 302 |
+
def forward(
|
| 303 |
+
self,
|
| 304 |
+
input_ids: torch.LongTensor | None = None,
|
| 305 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 306 |
+
high_res_pixel_values: torch.FloatTensor | None = None,
|
| 307 |
+
attention_mask: torch.Tensor | None = None,
|
| 308 |
+
position_ids: torch.LongTensor | None = None,
|
| 309 |
+
past_key_values: Cache | None = None,
|
| 310 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 311 |
+
use_cache: bool | None = None,
|
| 312 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 313 |
+
**kwargs,
|
| 314 |
+
) -> DeepseekVLHybridBaseModelOutputWithPast:
|
| 315 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 316 |
+
raise ValueError(
|
| 317 |
+
"You cannot specify both input_ids and inputs_embeds at the same time, and must specify either one"
|
| 318 |
+
)
|
| 319 |
+
|
| 320 |
+
if pixel_values is not None and high_res_pixel_values is None:
|
| 321 |
+
raise ValueError("Both pixel_values and high_res_pixel_values should be specified at the same time")
|
| 322 |
+
|
| 323 |
+
if inputs_embeds is None:
|
| 324 |
+
inputs_embeds = self.get_input_embeddings()(input_ids)
|
| 325 |
+
|
| 326 |
+
if pixel_values is not None:
|
| 327 |
+
if input_ids is None:
|
| 328 |
+
image_attention_mask = inputs_embeds == self.get_input_embeddings()(
|
| 329 |
+
torch.tensor(self.config.image_token_id, dtype=torch.long, device=inputs_embeds.device)
|
| 330 |
+
)
|
| 331 |
+
image_attention_mask = image_attention_mask.all(-1)
|
| 332 |
+
else:
|
| 333 |
+
image_attention_mask = input_ids == self.config.image_token_id
|
| 334 |
+
|
| 335 |
+
image_attention_mask = image_attention_mask.unsqueeze(-1).expand_as(inputs_embeds).to(inputs_embeds.device)
|
| 336 |
+
image_embeds = self.get_image_features(pixel_values, high_res_pixel_values, return_dict=True).pooler_output
|
| 337 |
+
image_features = image_embeds.reshape(-1, inputs_embeds.shape[-1])
|
| 338 |
+
image_features = image_features.to(inputs_embeds.device, inputs_embeds.dtype)
|
| 339 |
+
inputs_embeds = inputs_embeds.masked_scatter(image_attention_mask, image_features)
|
| 340 |
+
|
| 341 |
+
lm_output = self.language_model(
|
| 342 |
+
inputs_embeds=inputs_embeds,
|
| 343 |
+
attention_mask=attention_mask,
|
| 344 |
+
position_ids=position_ids,
|
| 345 |
+
past_key_values=past_key_values,
|
| 346 |
+
use_cache=use_cache,
|
| 347 |
+
logits_to_keep=logits_to_keep,
|
| 348 |
+
**kwargs,
|
| 349 |
+
)
|
| 350 |
+
|
| 351 |
+
return DeepseekVLHybridBaseModelOutputWithPast(
|
| 352 |
+
last_hidden_state=lm_output.last_hidden_state,
|
| 353 |
+
past_key_values=lm_output.past_key_values,
|
| 354 |
+
hidden_states=lm_output.hidden_states,
|
| 355 |
+
attentions=lm_output.attentions,
|
| 356 |
+
image_hidden_states=image_embeds if pixel_values is not None else None,
|
| 357 |
+
)
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
class DeepseekVLHybridForConditionalGeneration(DeepseekVLForConditionalGeneration):
|
| 361 |
+
@can_return_tuple
|
| 362 |
+
@auto_docstring(custom_args=DEEPSEEK_VL_COMMON_CUSTOM_ARGS)
|
| 363 |
+
def forward(
|
| 364 |
+
self,
|
| 365 |
+
input_ids: torch.LongTensor | None = None,
|
| 366 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 367 |
+
high_res_pixel_values: torch.FloatTensor | None = None,
|
| 368 |
+
attention_mask: torch.Tensor | None = None,
|
| 369 |
+
position_ids: torch.LongTensor | None = None,
|
| 370 |
+
past_key_values: Cache | None = None,
|
| 371 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 372 |
+
labels: torch.LongTensor | None = None,
|
| 373 |
+
use_cache: bool | None = None,
|
| 374 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 375 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 376 |
+
) -> DeepseekVLHybridCausalLMOutputWithPast:
|
| 377 |
+
r"""
|
| 378 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 379 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 380 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 381 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 382 |
+
"""
|
| 383 |
+
outputs = self.model(
|
| 384 |
+
input_ids=input_ids,
|
| 385 |
+
pixel_values=pixel_values,
|
| 386 |
+
high_res_pixel_values=high_res_pixel_values,
|
| 387 |
+
attention_mask=attention_mask,
|
| 388 |
+
position_ids=position_ids,
|
| 389 |
+
past_key_values=past_key_values,
|
| 390 |
+
inputs_embeds=inputs_embeds,
|
| 391 |
+
use_cache=use_cache,
|
| 392 |
+
**kwargs,
|
| 393 |
+
)
|
| 394 |
+
hidden_states = outputs.last_hidden_state
|
| 395 |
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
| 396 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 397 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
| 398 |
+
|
| 399 |
+
loss = None
|
| 400 |
+
if labels is not None:
|
| 401 |
+
loss = self.loss_function(
|
| 402 |
+
logits=logits, labels=labels, vocab_size=self.config.text_config.vocab_size, **kwargs
|
| 403 |
+
)
|
| 404 |
+
|
| 405 |
+
return DeepseekVLHybridCausalLMOutputWithPast(
|
| 406 |
+
loss=loss,
|
| 407 |
+
logits=logits,
|
| 408 |
+
past_key_values=outputs.past_key_values,
|
| 409 |
+
hidden_states=outputs.hidden_states,
|
| 410 |
+
attentions=outputs.attentions,
|
| 411 |
+
image_hidden_states=outputs.image_hidden_states,
|
| 412 |
+
)
|
| 413 |
+
|
| 414 |
+
def prepare_inputs_for_generation(
|
| 415 |
+
self,
|
| 416 |
+
input_ids,
|
| 417 |
+
past_key_values=None,
|
| 418 |
+
inputs_embeds=None,
|
| 419 |
+
pixel_values=None,
|
| 420 |
+
high_res_pixel_values=None,
|
| 421 |
+
attention_mask=None,
|
| 422 |
+
logits_to_keep=None,
|
| 423 |
+
is_first_iteration=False,
|
| 424 |
+
**kwargs,
|
| 425 |
+
):
|
| 426 |
+
model_inputs = super().prepare_inputs_for_generation(
|
| 427 |
+
input_ids,
|
| 428 |
+
past_key_values=past_key_values,
|
| 429 |
+
inputs_embeds=inputs_embeds,
|
| 430 |
+
attention_mask=attention_mask,
|
| 431 |
+
logits_to_keep=logits_to_keep,
|
| 432 |
+
is_first_iteration=is_first_iteration,
|
| 433 |
+
**kwargs,
|
| 434 |
+
)
|
| 435 |
+
|
| 436 |
+
if is_first_iteration or not kwargs.get("use_cache", True):
|
| 437 |
+
# Pixel values are used only in the first iteration if available
|
| 438 |
+
# In subsequent iterations, they are already merged with text and cached
|
| 439 |
+
# NOTE: first iteration doesn't have to be prefill, it can be the first
|
| 440 |
+
# iteration with a question and cached system prompt (continue generate from cache)
|
| 441 |
+
model_inputs["pixel_values"] = pixel_values
|
| 442 |
+
model_inputs["high_res_pixel_values"] = high_res_pixel_values
|
| 443 |
+
|
| 444 |
+
return model_inputs
|
| 445 |
+
|
| 446 |
+
|
| 447 |
+
class DeepseekVLHybridImageProcessorKwargs(ImagesKwargs, total=False):
|
| 448 |
+
r"""
|
| 449 |
+
min_size (`int`, *optional*, defaults to 14):
|
| 450 |
+
The minimum allowed size for the resized image. Ensures that neither the height nor width
|
| 451 |
+
falls below this value after resizing.
|
| 452 |
+
high_res_size (`dict`, *optional*, defaults to `{"height": 1024, "width": 1024}`):
|
| 453 |
+
Size of the high resolution output image after resizing. Can be overridden by the `high_res_size` parameter in the `preprocess`
|
| 454 |
+
method.
|
| 455 |
+
high_res_resample (`PILImageResampling`, *optional*, defaults to `Resampling.BICUBIC`):
|
| 456 |
+
Resampling filter to use if resizing the image. Only has an effect if `do_resize` is set to `True`. Can be
|
| 457 |
+
overridden by the `high_res_resample` parameter in the `preprocess` method.
|
| 458 |
+
high_res_image_mean (`float` or `list[float]`, *optional*, defaults to `OPENAI_CLIP_MEAN`):
|
| 459 |
+
Mean to use if normalizing the high resolution image. This is a float or list of floats the length of the number of
|
| 460 |
+
channels in the image. Can be overridden by the `high_res_image_mean` parameter in the `preprocess` method.
|
| 461 |
+
high_res_image_std (`float` or `list[float]`, *optional*, defaults to `OPENAI_CLIP_STD`):
|
| 462 |
+
Standard deviation to use if normalizing the high resolution image. This is a float or list of floats the length of the
|
| 463 |
+
number of channels in the image. Can be overridden by the `high_res_image_std` parameter in the `preprocess` method.
|
| 464 |
+
"""
|
| 465 |
+
|
| 466 |
+
min_size: int
|
| 467 |
+
high_res_size: dict
|
| 468 |
+
high_res_resample: Union["PILImageResampling", int]
|
| 469 |
+
high_res_image_mean: float | list[float] | tuple[float, ...]
|
| 470 |
+
high_res_image_std: float | list[float] | tuple[float, ...]
|
| 471 |
+
|
| 472 |
+
|
| 473 |
+
class DeepseekVLHybridImageProcessorPil(DeepseekVLImageProcessorPil):
|
| 474 |
+
high_res_image_mean = OPENAI_CLIP_MEAN
|
| 475 |
+
high_res_image_std = OPENAI_CLIP_STD
|
| 476 |
+
high_res_size = {"height": 1024, "width": 1024}
|
| 477 |
+
high_res_resample = PILImageResampling.BICUBIC
|
| 478 |
+
model_input_names = ["pixel_values", "high_res_pixel_values"]
|
| 479 |
+
|
| 480 |
+
def __init__(self, **kwargs: Unpack[DeepseekVLHybridImageProcessorKwargs]):
|
| 481 |
+
if kwargs.get("image_mean") is None:
|
| 482 |
+
background_color = (127, 127, 127)
|
| 483 |
+
else:
|
| 484 |
+
background_color = tuple(int(x * 255) for x in kwargs.get("image_mean"))
|
| 485 |
+
if kwargs.get("high_res_image_mean") is None:
|
| 486 |
+
high_res_background_color = (127, 127, 127)
|
| 487 |
+
else:
|
| 488 |
+
high_res_background_color = tuple(int(x * 255) for x in kwargs.get("high_res_image_mean"))
|
| 489 |
+
PilBackend.__init__(self, **kwargs)
|
| 490 |
+
self.background_color = tuple(background_color)
|
| 491 |
+
self.high_res_background_color = tuple(high_res_background_color)
|
| 492 |
+
|
| 493 |
+
def _standardize_kwargs(
|
| 494 |
+
self,
|
| 495 |
+
size: int | Iterable[int] | dict[str, int] | SizeDict | None = None,
|
| 496 |
+
high_res_size: int | Iterable[int] | dict[str, int] | SizeDict | None = None,
|
| 497 |
+
default_to_square: bool | None = None,
|
| 498 |
+
image_mean: float | list[float] | None = None,
|
| 499 |
+
image_std: float | list[float] | None = None,
|
| 500 |
+
high_res_image_mean: float | list[float] | None = None,
|
| 501 |
+
high_res_image_std: float | list[float] | None = None,
|
| 502 |
+
**kwargs,
|
| 503 |
+
) -> dict:
|
| 504 |
+
"""
|
| 505 |
+
Update kwargs that need further processing before being validated
|
| 506 |
+
Can be overridden by subclasses to customize the processing of kwargs.
|
| 507 |
+
"""
|
| 508 |
+
if kwargs is None:
|
| 509 |
+
kwargs = {}
|
| 510 |
+
if size is not None and not isinstance(size, SizeDict):
|
| 511 |
+
size = SizeDict(**get_size_dict(size=size, default_to_square=default_to_square))
|
| 512 |
+
if high_res_size is not None and not isinstance(high_res_size, SizeDict):
|
| 513 |
+
high_res_size = SizeDict(**get_size_dict(size=high_res_size, default_to_square=default_to_square))
|
| 514 |
+
if isinstance(image_mean, list):
|
| 515 |
+
image_mean = tuple(image_mean)
|
| 516 |
+
if isinstance(image_std, list):
|
| 517 |
+
image_std = tuple(image_std)
|
| 518 |
+
if isinstance(high_res_image_mean, list):
|
| 519 |
+
high_res_image_mean = tuple(high_res_image_mean)
|
| 520 |
+
if isinstance(high_res_image_std, list):
|
| 521 |
+
high_res_image_std = tuple(high_res_image_std)
|
| 522 |
+
|
| 523 |
+
kwargs["size"] = size
|
| 524 |
+
kwargs["high_res_size"] = high_res_size
|
| 525 |
+
kwargs["image_mean"] = image_mean
|
| 526 |
+
kwargs["image_std"] = image_std
|
| 527 |
+
kwargs["high_res_image_mean"] = high_res_image_mean
|
| 528 |
+
kwargs["high_res_image_std"] = high_res_image_std
|
| 529 |
+
|
| 530 |
+
return kwargs
|
| 531 |
+
|
| 532 |
+
def _preprocess(
|
| 533 |
+
self,
|
| 534 |
+
images: list[np.ndarray],
|
| 535 |
+
do_resize: bool,
|
| 536 |
+
size: SizeDict,
|
| 537 |
+
high_res_size: SizeDict,
|
| 538 |
+
min_size: int,
|
| 539 |
+
resample: "PILImageResampling | None",
|
| 540 |
+
high_res_resample: "PILImageResampling | None",
|
| 541 |
+
do_rescale: bool,
|
| 542 |
+
rescale_factor: float,
|
| 543 |
+
do_normalize: bool,
|
| 544 |
+
image_mean: float | list[float] | None,
|
| 545 |
+
image_std: float | list[float] | None,
|
| 546 |
+
high_res_image_mean: float | list[float] | None,
|
| 547 |
+
high_res_image_std: float | list[float] | None,
|
| 548 |
+
return_tensors: str | TensorType | None,
|
| 549 |
+
do_pad: bool = True,
|
| 550 |
+
**kwargs,
|
| 551 |
+
) -> BatchFeature:
|
| 552 |
+
high_res_processed_images = []
|
| 553 |
+
processed_images = []
|
| 554 |
+
for image in images:
|
| 555 |
+
# high_res_image: resize (high) -> rescale -> normalize (high)
|
| 556 |
+
# low_res_image: resize (high) -> rescale -> resize (low) -> normalize (low)
|
| 557 |
+
high_res_image = image
|
| 558 |
+
if do_resize:
|
| 559 |
+
high_res_image = self.resize(
|
| 560 |
+
image=high_res_image, size=high_res_size, min_size=min_size, resample=high_res_resample
|
| 561 |
+
)
|
| 562 |
+
if do_pad:
|
| 563 |
+
high_res_image = self.pad_to_square(
|
| 564 |
+
high_res_image, background_color=self.high_res_background_color
|
| 565 |
+
)
|
| 566 |
+
image = self.resize(image=high_res_image, size=size, min_size=min_size, resample=resample)
|
| 567 |
+
if do_pad:
|
| 568 |
+
image = self.pad_to_square(image, background_color=self.background_color)
|
| 569 |
+
if do_rescale:
|
| 570 |
+
high_res_image = self.rescale(high_res_image, rescale_factor)
|
| 571 |
+
image = self.rescale(image, rescale_factor)
|
| 572 |
+
if do_normalize:
|
| 573 |
+
high_res_image = self.normalize(high_res_image, high_res_image_mean, high_res_image_std)
|
| 574 |
+
image = self.normalize(image, image_mean, image_std)
|
| 575 |
+
processed_images.append(image)
|
| 576 |
+
high_res_processed_images.append(high_res_image)
|
| 577 |
+
|
| 578 |
+
return BatchFeature(
|
| 579 |
+
data={"pixel_values": processed_images, "high_res_pixel_values": high_res_processed_images},
|
| 580 |
+
tensor_type=return_tensors,
|
| 581 |
+
)
|
| 582 |
+
|
| 583 |
+
|
| 584 |
+
class DeepseekVLHybridImageProcessor(DeepseekVLImageProcessor):
|
| 585 |
+
high_res_image_mean = OPENAI_CLIP_MEAN
|
| 586 |
+
high_res_image_std = OPENAI_CLIP_STD
|
| 587 |
+
high_res_size = {"height": 1024, "width": 1024}
|
| 588 |
+
high_res_resample = PILImageResampling.BICUBIC
|
| 589 |
+
model_input_names = ["pixel_values", "high_res_pixel_values"]
|
| 590 |
+
|
| 591 |
+
def __init__(self, **kwargs: Unpack[DeepseekVLHybridImageProcessorKwargs]):
|
| 592 |
+
if kwargs.get("image_mean") is None:
|
| 593 |
+
background_color = (127, 127, 127)
|
| 594 |
+
else:
|
| 595 |
+
background_color = tuple(int(x * 255) for x in kwargs.get("image_mean"))
|
| 596 |
+
if kwargs.get("high_res_image_mean") is None:
|
| 597 |
+
high_res_background_color = (127, 127, 127)
|
| 598 |
+
else:
|
| 599 |
+
high_res_background_color = tuple(int(x * 255) for x in kwargs.get("high_res_image_mean"))
|
| 600 |
+
TorchvisionBackend.__init__(self, **kwargs)
|
| 601 |
+
self.background_color = tuple(background_color)
|
| 602 |
+
self.high_res_background_color = tuple(high_res_background_color)
|
| 603 |
+
|
| 604 |
+
def _standardize_kwargs(
|
| 605 |
+
self,
|
| 606 |
+
size: int | Iterable[int] | dict[str, int] | SizeDict | None = None,
|
| 607 |
+
high_res_size: int | Iterable[int] | dict[str, int] | SizeDict | None = None,
|
| 608 |
+
default_to_square: bool | None = None,
|
| 609 |
+
image_mean: float | list[float] | None = None,
|
| 610 |
+
image_std: float | list[float] | None = None,
|
| 611 |
+
high_res_image_mean: float | list[float] | None = None,
|
| 612 |
+
high_res_image_std: float | list[float] | None = None,
|
| 613 |
+
**kwargs,
|
| 614 |
+
) -> dict:
|
| 615 |
+
"""
|
| 616 |
+
Update kwargs that need further processing before being validated
|
| 617 |
+
Can be overridden by subclasses to customize the processing of kwargs.
|
| 618 |
+
"""
|
| 619 |
+
if kwargs is None:
|
| 620 |
+
kwargs = {}
|
| 621 |
+
if size is not None and not isinstance(size, SizeDict):
|
| 622 |
+
size = SizeDict(**get_size_dict(size=size, default_to_square=default_to_square))
|
| 623 |
+
if high_res_size is not None and not isinstance(high_res_size, SizeDict):
|
| 624 |
+
high_res_size = SizeDict(**get_size_dict(size=high_res_size, default_to_square=default_to_square))
|
| 625 |
+
if isinstance(image_mean, list):
|
| 626 |
+
image_mean = tuple(image_mean)
|
| 627 |
+
if isinstance(image_std, list):
|
| 628 |
+
image_std = tuple(image_std)
|
| 629 |
+
if isinstance(high_res_image_mean, list):
|
| 630 |
+
high_res_image_mean = tuple(high_res_image_mean)
|
| 631 |
+
if isinstance(high_res_image_std, list):
|
| 632 |
+
high_res_image_std = tuple(high_res_image_std)
|
| 633 |
+
|
| 634 |
+
kwargs["size"] = size
|
| 635 |
+
kwargs["high_res_size"] = high_res_size
|
| 636 |
+
kwargs["image_mean"] = image_mean
|
| 637 |
+
kwargs["image_std"] = image_std
|
| 638 |
+
kwargs["high_res_image_mean"] = high_res_image_mean
|
| 639 |
+
kwargs["high_res_image_std"] = high_res_image_std
|
| 640 |
+
|
| 641 |
+
return kwargs
|
| 642 |
+
|
| 643 |
+
def _preprocess(
|
| 644 |
+
self,
|
| 645 |
+
images: list["torch.Tensor"],
|
| 646 |
+
do_resize: bool,
|
| 647 |
+
size: SizeDict,
|
| 648 |
+
high_res_size: SizeDict,
|
| 649 |
+
min_size: int,
|
| 650 |
+
resample: "PILImageResampling | None",
|
| 651 |
+
high_res_resample: "PILImageResampling | None",
|
| 652 |
+
do_rescale: bool,
|
| 653 |
+
rescale_factor: float,
|
| 654 |
+
do_normalize: bool,
|
| 655 |
+
image_mean: float | list[float] | None,
|
| 656 |
+
image_std: float | list[float] | None,
|
| 657 |
+
high_res_image_mean: float | list[float] | None,
|
| 658 |
+
high_res_image_std: float | list[float] | None,
|
| 659 |
+
disable_grouping: bool | None,
|
| 660 |
+
return_tensors: str | TensorType | None,
|
| 661 |
+
do_pad: bool = True,
|
| 662 |
+
**kwargs,
|
| 663 |
+
) -> BatchFeature:
|
| 664 |
+
# Group images by size for batched resizing
|
| 665 |
+
grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
|
| 666 |
+
high_res_resized_images_grouped = {}
|
| 667 |
+
for shape, stacked_images in grouped_images.items():
|
| 668 |
+
if do_resize:
|
| 669 |
+
stacked_high_res_images = self.resize(
|
| 670 |
+
image=stacked_images, size=high_res_size, min_size=min_size, resample=high_res_resample
|
| 671 |
+
)
|
| 672 |
+
high_res_resized_images_grouped[shape] = stacked_high_res_images
|
| 673 |
+
high_res_resized_images = reorder_images(high_res_resized_images_grouped, grouped_images_index)
|
| 674 |
+
|
| 675 |
+
# Group images by size for further processing
|
| 676 |
+
# Needed in case do_resize is False, or resize returns images with different sizes
|
| 677 |
+
grouped_high_res_images, grouped_high_res_images_index = group_images_by_shape(
|
| 678 |
+
high_res_resized_images, disable_grouping=disable_grouping
|
| 679 |
+
)
|
| 680 |
+
high_res_padded_images = {}
|
| 681 |
+
high_res_processed_images_grouped = {}
|
| 682 |
+
for shape, stacked_high_res_images in grouped_high_res_images.items():
|
| 683 |
+
if do_pad:
|
| 684 |
+
stacked_high_res_images = self.pad_to_square(
|
| 685 |
+
stacked_high_res_images, background_color=self.high_res_background_color
|
| 686 |
+
)
|
| 687 |
+
high_res_padded_images[shape] = stacked_high_res_images
|
| 688 |
+
# Fused rescale and normalize
|
| 689 |
+
stacked_high_res_images = self.rescale_and_normalize(
|
| 690 |
+
stacked_high_res_images,
|
| 691 |
+
do_rescale,
|
| 692 |
+
rescale_factor,
|
| 693 |
+
do_normalize,
|
| 694 |
+
high_res_image_mean,
|
| 695 |
+
high_res_image_std,
|
| 696 |
+
)
|
| 697 |
+
high_res_processed_images_grouped[shape] = stacked_high_res_images
|
| 698 |
+
high_res_processed_images = reorder_images(high_res_processed_images_grouped, grouped_high_res_images_index)
|
| 699 |
+
|
| 700 |
+
resized_images_grouped = {}
|
| 701 |
+
for shape, stacked_high_res_padded_images in high_res_padded_images.items():
|
| 702 |
+
if do_resize:
|
| 703 |
+
stacked_images = self.resize(
|
| 704 |
+
image=stacked_high_res_padded_images, size=size, min_size=min_size, resample=resample
|
| 705 |
+
)
|
| 706 |
+
resized_images_grouped[shape] = stacked_images
|
| 707 |
+
resized_images = reorder_images(resized_images_grouped, grouped_high_res_images_index)
|
| 708 |
+
|
| 709 |
+
grouped_resized_images, grouped_resized_images_index = group_images_by_shape(
|
| 710 |
+
resized_images, disable_grouping=disable_grouping
|
| 711 |
+
)
|
| 712 |
+
processed_images_grouped = {}
|
| 713 |
+
for shape, stacked_images in grouped_resized_images.items():
|
| 714 |
+
if do_pad:
|
| 715 |
+
stacked_images = self.pad_to_square(stacked_images, background_color=self.background_color)
|
| 716 |
+
# Fused rescale and normalize
|
| 717 |
+
stacked_images = self.rescale_and_normalize(
|
| 718 |
+
stacked_images, do_rescale, rescale_factor, do_normalize, image_mean, image_std
|
| 719 |
+
)
|
| 720 |
+
processed_images_grouped[shape] = stacked_images
|
| 721 |
+
processed_images = reorder_images(processed_images_grouped, grouped_resized_images_index)
|
| 722 |
+
|
| 723 |
+
return BatchFeature(
|
| 724 |
+
data={"pixel_values": processed_images, "high_res_pixel_values": high_res_processed_images},
|
| 725 |
+
tensor_type=return_tensors,
|
| 726 |
+
)
|
| 727 |
+
|
| 728 |
+
|
| 729 |
+
class DeepseekVLHybridProcessorKwargs(DeepseekVLProcessorKwargs):
|
| 730 |
+
pass
|
| 731 |
+
|
| 732 |
+
|
| 733 |
+
class DeepseekVLHybridProcessor(DeepseekVLProcessor):
|
| 734 |
+
def __call__(
|
| 735 |
+
self,
|
| 736 |
+
text: TextInput | PreTokenizedInput | list[TextInput] | list[PreTokenizedInput] = None,
|
| 737 |
+
images: ImageInput | None = None,
|
| 738 |
+
**kwargs: Unpack[DeepseekVLHybridProcessorKwargs],
|
| 739 |
+
) -> BatchFeature:
|
| 740 |
+
r"""
|
| 741 |
+
Returns:
|
| 742 |
+
[`BatchFeature`]: A [`BatchFeature`] with the following fields:
|
| 743 |
+
|
| 744 |
+
- **input_ids** -- List of token ids to be fed to a model. Returned when `text` is not `None`.
|
| 745 |
+
- **attention_mask** -- List of indices specifying which tokens should be attended to by the model (when
|
| 746 |
+
`return_attention_mask=True` or if *"attention_mask"* is in `self.model_input_names` and if `text` is not
|
| 747 |
+
`None`).
|
| 748 |
+
- **pixel_values** -- Pixel values to be fed to a model. Returned when `images` is not `None`.
|
| 749 |
+
"""
|
| 750 |
+
output_kwargs = self._merge_kwargs(
|
| 751 |
+
DeepseekVLHybridProcessorKwargs, tokenizer_init_kwargs=self.tokenizer.init_kwargs, **kwargs
|
| 752 |
+
)
|
| 753 |
+
if text is None and images is None:
|
| 754 |
+
raise ValueError("You must specify either text or images.")
|
| 755 |
+
|
| 756 |
+
if text is not None:
|
| 757 |
+
if isinstance(text, str):
|
| 758 |
+
text = [text]
|
| 759 |
+
elif not (isinstance(text, (list, tuple)) and all(isinstance(t, str) for t in text)):
|
| 760 |
+
raise ValueError("Invalid input text. Please provide a string, or a list of strings")
|
| 761 |
+
|
| 762 |
+
prompt_strings = []
|
| 763 |
+
one_img_tokens = self.image_token * self.num_image_tokens
|
| 764 |
+
for prompt in text:
|
| 765 |
+
prompt = prompt.replace(self.image_token, one_img_tokens)
|
| 766 |
+
prompt_strings.append(prompt)
|
| 767 |
+
|
| 768 |
+
data = self.tokenizer(prompt_strings, **output_kwargs["text_kwargs"])
|
| 769 |
+
|
| 770 |
+
# process images if pixel_values are provided
|
| 771 |
+
if images is not None:
|
| 772 |
+
inputs = self.image_processor(images, **output_kwargs["images_kwargs"])
|
| 773 |
+
data["pixel_values"] = inputs["pixel_values"]
|
| 774 |
+
data["high_res_pixel_values"] = inputs["high_res_pixel_values"]
|
| 775 |
+
|
| 776 |
+
return BatchFeature(data=data)
|
| 777 |
+
|
| 778 |
+
|
| 779 |
+
__all__ = [
|
| 780 |
+
"DeepseekVLHybridConfig",
|
| 781 |
+
"DeepseekVLHybridPreTrainedModel",
|
| 782 |
+
"DeepseekVLHybridModel",
|
| 783 |
+
"DeepseekVLHybridForConditionalGeneration",
|
| 784 |
+
"DeepseekVLHybridImageProcessor",
|
| 785 |
+
"DeepseekVLHybridImageProcessorPil",
|
| 786 |
+
"DeepseekVLHybridProcessor",
|
| 787 |
+
]
|
third_party/transformers/src/transformers/models/deepseek_vl_hybrid/processing_deepseek_vl_hybrid.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.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_deepseek_vl_hybrid.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 Deepseek AI and The HuggingFace Team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from ...image_processing_utils import BatchFeature
|
| 22 |
+
from ...image_utils import ImageInput
|
| 23 |
+
from ...processing_utils import ProcessingKwargs, ProcessorMixin, Unpack
|
| 24 |
+
from ...tokenization_utils_base import PreTokenizedInput, TextInput
|
| 25 |
+
from ...utils import auto_docstring
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
class DeepseekVLHybridProcessorKwargs(ProcessingKwargs, total=False):
|
| 29 |
+
_defaults = {
|
| 30 |
+
"text_kwargs": {"padding": False},
|
| 31 |
+
"common_kwargs": {"return_tensors": "pt"},
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
@auto_docstring
|
| 36 |
+
class DeepseekVLHybridProcessor(ProcessorMixin):
|
| 37 |
+
def __init__(
|
| 38 |
+
self,
|
| 39 |
+
image_processor,
|
| 40 |
+
tokenizer,
|
| 41 |
+
chat_template=None,
|
| 42 |
+
num_image_tokens=576,
|
| 43 |
+
):
|
| 44 |
+
r"""
|
| 45 |
+
num_image_tokens (`int`, *optional*, defaults to 576):
|
| 46 |
+
The number of special image tokens used as placeholders for visual content in text sequences.
|
| 47 |
+
"""
|
| 48 |
+
self.image_token = tokenizer.image_token
|
| 49 |
+
self.num_image_tokens = num_image_tokens
|
| 50 |
+
|
| 51 |
+
super().__init__(image_processor, tokenizer, chat_template=chat_template)
|
| 52 |
+
|
| 53 |
+
@auto_docstring
|
| 54 |
+
def __call__(
|
| 55 |
+
self,
|
| 56 |
+
text: TextInput | PreTokenizedInput | list[TextInput] | list[PreTokenizedInput] = None,
|
| 57 |
+
images: ImageInput | None = None,
|
| 58 |
+
**kwargs: Unpack[DeepseekVLHybridProcessorKwargs],
|
| 59 |
+
) -> BatchFeature:
|
| 60 |
+
r"""
|
| 61 |
+
Returns:
|
| 62 |
+
[`BatchFeature`]: A [`BatchFeature`] with the following fields:
|
| 63 |
+
|
| 64 |
+
- **input_ids** -- List of token ids to be fed to a model. Returned when `text` is not `None`.
|
| 65 |
+
- **attention_mask** -- List of indices specifying which tokens should be attended to by the model (when
|
| 66 |
+
`return_attention_mask=True` or if *"attention_mask"* is in `self.model_input_names` and if `text` is not
|
| 67 |
+
`None`).
|
| 68 |
+
- **pixel_values** -- Pixel values to be fed to a model. Returned when `images` is not `None`.
|
| 69 |
+
"""
|
| 70 |
+
output_kwargs = self._merge_kwargs(
|
| 71 |
+
DeepseekVLHybridProcessorKwargs, tokenizer_init_kwargs=self.tokenizer.init_kwargs, **kwargs
|
| 72 |
+
)
|
| 73 |
+
if text is None and images is None:
|
| 74 |
+
raise ValueError("You must specify either text or images.")
|
| 75 |
+
|
| 76 |
+
if text is not None:
|
| 77 |
+
if isinstance(text, str):
|
| 78 |
+
text = [text]
|
| 79 |
+
elif not (isinstance(text, (list, tuple)) and all(isinstance(t, str) for t in text)):
|
| 80 |
+
raise ValueError("Invalid input text. Please provide a string, or a list of strings")
|
| 81 |
+
|
| 82 |
+
prompt_strings = []
|
| 83 |
+
one_img_tokens = self.image_token * self.num_image_tokens
|
| 84 |
+
for prompt in text:
|
| 85 |
+
prompt = prompt.replace(self.image_token, one_img_tokens)
|
| 86 |
+
prompt_strings.append(prompt)
|
| 87 |
+
|
| 88 |
+
data = self.tokenizer(prompt_strings, **output_kwargs["text_kwargs"])
|
| 89 |
+
|
| 90 |
+
# process images if pixel_values are provided
|
| 91 |
+
if images is not None:
|
| 92 |
+
inputs = self.image_processor(images, **output_kwargs["images_kwargs"])
|
| 93 |
+
data["pixel_values"] = inputs["pixel_values"]
|
| 94 |
+
data["high_res_pixel_values"] = inputs["high_res_pixel_values"]
|
| 95 |
+
|
| 96 |
+
return BatchFeature(data=data)
|
| 97 |
+
|
| 98 |
+
def batch_decode(self, *args, **kwargs):
|
| 99 |
+
"""
|
| 100 |
+
This method forwards all its arguments to LlamaTokenizerFast's [`~PreTrainedTokenizer.batch_decode`]. Please
|
| 101 |
+
refer to the docstring of this method for more information.
|
| 102 |
+
"""
|
| 103 |
+
return self.tokenizer.batch_decode(*args, **kwargs)
|
| 104 |
+
|
| 105 |
+
def decode(self, *args, **kwargs):
|
| 106 |
+
"""
|
| 107 |
+
This method forwards all its arguments to LlamaTokenizerFast's [`~PreTrainedTokenizer.decode`]. Please refer to
|
| 108 |
+
the docstring of this method for more information.
|
| 109 |
+
"""
|
| 110 |
+
return self.tokenizer.decode(*args, **kwargs)
|
| 111 |
+
|
| 112 |
+
@property
|
| 113 |
+
def model_input_names(self):
|
| 114 |
+
tokenizer_input_names = self.tokenizer.model_input_names
|
| 115 |
+
image_processor_input_names = self.image_processor.model_input_names
|
| 116 |
+
return list(dict.fromkeys(tokenizer_input_names + image_processor_input_names))
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
__all__ = ["DeepseekVLHybridProcessor"]
|
third_party/transformers/src/transformers/models/diffllama/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
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_diffllama import *
|
| 22 |
+
from .modeling_diffllama import *
|
| 23 |
+
else:
|
| 24 |
+
import sys
|
| 25 |
+
|
| 26 |
+
_file = globals()["__file__"]
|
| 27 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/diffllama/configuration_diffllama.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 weak-kajuma and the HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# This code is based on Llama implementations in this library and Microsoft's
|
| 4 |
+
# Differential Transformer implementations.
|
| 5 |
+
|
| 6 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 7 |
+
# you may not use this file except in compliance with the License.
|
| 8 |
+
# You may obtain a copy of the License at
|
| 9 |
+
#
|
| 10 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 11 |
+
#
|
| 12 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 13 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 14 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 15 |
+
# See the License for the specific language governing permissions and
|
| 16 |
+
# limitations under the License.
|
| 17 |
+
"""DiffLlama model configuration"""
|
| 18 |
+
|
| 19 |
+
from huggingface_hub.dataclasses import strict
|
| 20 |
+
|
| 21 |
+
from ...configuration_utils import PreTrainedConfig
|
| 22 |
+
from ...modeling_rope_utils import RopeParameters
|
| 23 |
+
from ...utils import auto_docstring
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
@auto_docstring(checkpoint="kajuma/DiffLlama-0.3B-handcut")
|
| 27 |
+
@strict
|
| 28 |
+
class DiffLlamaConfig(PreTrainedConfig):
|
| 29 |
+
r"""
|
| 30 |
+
lambda_std_dev (`float`, *optional*, defaults to 0.1):
|
| 31 |
+
The standard deviation for initialization of parameter lambda in attention layer.
|
| 32 |
+
|
| 33 |
+
```python
|
| 34 |
+
>>> from transformers import DiffLlamaModel, DiffLlamaConfig
|
| 35 |
+
|
| 36 |
+
>>> # Initializing a DiffLlama diffllama-7b style configuration
|
| 37 |
+
>>> configuration = DiffLlamaConfig()
|
| 38 |
+
|
| 39 |
+
>>> # Initializing a model from the diffllama-7b style configuration
|
| 40 |
+
>>> model = DiffLlamaModel(configuration)
|
| 41 |
+
|
| 42 |
+
>>> # Accessing the model configuration
|
| 43 |
+
>>> configuration = model.config
|
| 44 |
+
```
|
| 45 |
+
"""
|
| 46 |
+
|
| 47 |
+
model_type = "diffllama"
|
| 48 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 49 |
+
|
| 50 |
+
vocab_size: int = 32000
|
| 51 |
+
hidden_size: int = 2048
|
| 52 |
+
intermediate_size: int = 8192
|
| 53 |
+
num_hidden_layers: int = 16
|
| 54 |
+
num_attention_heads: int = 32
|
| 55 |
+
num_key_value_heads: int | None = None
|
| 56 |
+
hidden_act: str = "silu"
|
| 57 |
+
max_position_embeddings: int = 2048
|
| 58 |
+
initializer_range: float = 0.02
|
| 59 |
+
rms_norm_eps: float = 1e-5
|
| 60 |
+
use_cache: bool = True
|
| 61 |
+
pad_token_id: int | None = None
|
| 62 |
+
bos_token_id: int | None = 1
|
| 63 |
+
eos_token_id: int | list[int] | None = 2
|
| 64 |
+
tie_word_embeddings: bool = False
|
| 65 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 66 |
+
attention_bias: bool = False
|
| 67 |
+
attention_dropout: float | int | None = 0.0
|
| 68 |
+
lambda_std_dev: float | None = 0.1
|
| 69 |
+
head_dim: int | None = None
|
| 70 |
+
|
| 71 |
+
def __post_init__(self, **kwargs):
|
| 72 |
+
# for backward compatibility
|
| 73 |
+
if self.num_key_value_heads is None:
|
| 74 |
+
self.num_key_value_heads = self.num_attention_heads
|
| 75 |
+
|
| 76 |
+
self.head_dim = self.head_dim if self.head_dim is not None else self.hidden_size // self.num_attention_heads
|
| 77 |
+
super().__post_init__(**kwargs)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
__all__ = ["DiffLlamaConfig"]
|
third_party/transformers/src/transformers/models/diffllama/modeling_diffllama.py
ADDED
|
@@ -0,0 +1,753 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/diffllama/modular_diffllama.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_diffllama.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2024 weak-kajuma and the HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# This code is based on Llama implementations in this library and Microsoft's
|
| 10 |
+
# Differential Transformer implementations.
|
| 11 |
+
|
| 12 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 13 |
+
# you may not use this file except in compliance with the License.
|
| 14 |
+
# You may obtain a copy of the License at
|
| 15 |
+
#
|
| 16 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 17 |
+
#
|
| 18 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 19 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 20 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 21 |
+
# See the License for the specific language governing permissions and
|
| 22 |
+
# limitations under the License.
|
| 23 |
+
import math
|
| 24 |
+
from collections.abc import Callable
|
| 25 |
+
from typing import Optional
|
| 26 |
+
|
| 27 |
+
import torch
|
| 28 |
+
from torch import nn
|
| 29 |
+
|
| 30 |
+
from ... import initialization as init
|
| 31 |
+
from ...activations import ACT2FN
|
| 32 |
+
from ...cache_utils import Cache, DynamicCache, StaticCache
|
| 33 |
+
from ...generation import GenerationMixin
|
| 34 |
+
from ...integrations import use_kernel_forward_from_hub, use_kernel_func_from_hub
|
| 35 |
+
from ...masking_utils import create_causal_mask
|
| 36 |
+
from ...modeling_flash_attention_utils import _flash_attention_forward, flash_attn_supports_top_left_mask
|
| 37 |
+
from ...modeling_layers import (
|
| 38 |
+
GenericForQuestionAnswering,
|
| 39 |
+
GenericForSequenceClassification,
|
| 40 |
+
GenericForTokenClassification,
|
| 41 |
+
GradientCheckpointingLayer,
|
| 42 |
+
)
|
| 43 |
+
from ...modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
|
| 44 |
+
from ...modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
|
| 45 |
+
from ...modeling_utils import PreTrainedModel
|
| 46 |
+
from ...processing_utils import Unpack
|
| 47 |
+
from ...utils import TransformersKwargs, auto_docstring, can_return_tuple, logging
|
| 48 |
+
from ...utils.generic import maybe_autocast, merge_with_config_defaults
|
| 49 |
+
from ...utils.output_capturing import capture_outputs
|
| 50 |
+
from .configuration_diffllama import DiffLlamaConfig
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
logger = logging.get_logger(__name__)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
class DiffLlamaMLP(nn.Module):
|
| 57 |
+
def __init__(self, config):
|
| 58 |
+
super().__init__()
|
| 59 |
+
self.config = config
|
| 60 |
+
self.hidden_size = config.hidden_size
|
| 61 |
+
self.intermediate_size = config.intermediate_size
|
| 62 |
+
self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 63 |
+
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 64 |
+
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
| 65 |
+
self.act_fn = ACT2FN[config.hidden_act]
|
| 66 |
+
|
| 67 |
+
def forward(self, x):
|
| 68 |
+
down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
|
| 69 |
+
return down_proj
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
class DiffLlamaRotaryEmbedding(nn.Module):
|
| 73 |
+
inv_freq: torch.Tensor # fix linting for `register_buffer`
|
| 74 |
+
|
| 75 |
+
def __init__(self, config: DiffLlamaConfig, device=None):
|
| 76 |
+
super().__init__()
|
| 77 |
+
self.max_seq_len_cached = config.max_position_embeddings
|
| 78 |
+
self.original_max_seq_len = config.max_position_embeddings
|
| 79 |
+
|
| 80 |
+
self.config = config
|
| 81 |
+
|
| 82 |
+
self.rope_type = self.config.rope_parameters["rope_type"]
|
| 83 |
+
rope_init_fn: Callable = self.compute_default_rope_parameters
|
| 84 |
+
if self.rope_type != "default":
|
| 85 |
+
rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
|
| 86 |
+
inv_freq, self.attention_scaling = rope_init_fn(self.config, device)
|
| 87 |
+
|
| 88 |
+
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
| 89 |
+
self.register_buffer("original_inv_freq", inv_freq.clone(), persistent=False)
|
| 90 |
+
|
| 91 |
+
@staticmethod
|
| 92 |
+
def compute_default_rope_parameters(
|
| 93 |
+
config: DiffLlamaConfig | None = None,
|
| 94 |
+
device: Optional["torch.device"] = None,
|
| 95 |
+
seq_len: int | None = None,
|
| 96 |
+
) -> tuple["torch.Tensor", float]:
|
| 97 |
+
"""
|
| 98 |
+
Computes the inverse frequencies according to the original RoPE implementation
|
| 99 |
+
Args:
|
| 100 |
+
config ([`~transformers.PreTrainedConfig`]):
|
| 101 |
+
The model configuration.
|
| 102 |
+
device (`torch.device`):
|
| 103 |
+
The device to use for initialization of the inverse frequencies.
|
| 104 |
+
seq_len (`int`, *optional*):
|
| 105 |
+
The current sequence length. Unused for this type of RoPE.
|
| 106 |
+
Returns:
|
| 107 |
+
Tuple of (`torch.Tensor`, `float`), containing the inverse frequencies for the RoPE embeddings and the
|
| 108 |
+
post-processing scaling factor applied to the computed cos/sin (unused in this type of RoPE).
|
| 109 |
+
"""
|
| 110 |
+
base = config.rope_parameters["rope_theta"]
|
| 111 |
+
dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
|
| 112 |
+
|
| 113 |
+
attention_factor = 1.0 # Unused in this type of RoPE
|
| 114 |
+
|
| 115 |
+
# Compute the inverse frequencies
|
| 116 |
+
inv_freq = 1.0 / (
|
| 117 |
+
base ** (torch.arange(0, dim, 2, dtype=torch.int64).to(device=device, dtype=torch.float) / dim)
|
| 118 |
+
)
|
| 119 |
+
return inv_freq, attention_factor
|
| 120 |
+
|
| 121 |
+
@torch.no_grad()
|
| 122 |
+
@dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
|
| 123 |
+
def forward(self, x, position_ids):
|
| 124 |
+
inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1).to(x.device)
|
| 125 |
+
position_ids_expanded = position_ids[:, None, :].float()
|
| 126 |
+
|
| 127 |
+
device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
|
| 128 |
+
with maybe_autocast(device_type=device_type, enabled=False): # Force float32
|
| 129 |
+
freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
|
| 130 |
+
emb = torch.cat((freqs, freqs), dim=-1)
|
| 131 |
+
cos = emb.cos() * self.attention_scaling
|
| 132 |
+
sin = emb.sin() * self.attention_scaling
|
| 133 |
+
|
| 134 |
+
return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def rotate_half(x):
|
| 138 |
+
"""Rotates half the hidden dims of the input."""
|
| 139 |
+
x1 = x[..., : x.shape[-1] // 2]
|
| 140 |
+
x2 = x[..., x.shape[-1] // 2 :]
|
| 141 |
+
return torch.cat((-x2, x1), dim=-1)
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
@use_kernel_func_from_hub("rotary_pos_emb")
|
| 145 |
+
def apply_rotary_pos_emb(q, k, cos, sin, unsqueeze_dim=1):
|
| 146 |
+
"""Applies Rotary Position Embedding to the query and key tensors.
|
| 147 |
+
|
| 148 |
+
Args:
|
| 149 |
+
q (`torch.Tensor`): The query tensor.
|
| 150 |
+
k (`torch.Tensor`): The key tensor.
|
| 151 |
+
cos (`torch.Tensor`): The cosine part of the rotary embedding.
|
| 152 |
+
sin (`torch.Tensor`): The sine part of the rotary embedding.
|
| 153 |
+
unsqueeze_dim (`int`, *optional*, defaults to 1):
|
| 154 |
+
The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
|
| 155 |
+
sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
|
| 156 |
+
that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
|
| 157 |
+
k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
|
| 158 |
+
cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
|
| 159 |
+
the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
|
| 160 |
+
Returns:
|
| 161 |
+
`tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
|
| 162 |
+
"""
|
| 163 |
+
cos = cos.unsqueeze(unsqueeze_dim)
|
| 164 |
+
sin = sin.unsqueeze(unsqueeze_dim)
|
| 165 |
+
q_embed = (q * cos) + (rotate_half(q) * sin)
|
| 166 |
+
k_embed = (k * cos) + (rotate_half(k) * sin)
|
| 167 |
+
return q_embed, k_embed
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 171 |
+
"""
|
| 172 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 173 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 174 |
+
"""
|
| 175 |
+
batch, num_key_value_heads, slen, head_dim = hidden_states.shape
|
| 176 |
+
if n_rep == 1:
|
| 177 |
+
return hidden_states
|
| 178 |
+
hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
|
| 179 |
+
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
def lambda_init_fn(layer_idx):
|
| 183 |
+
return 0.8 - 0.6 * math.exp(-0.3 * layer_idx)
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
class DiffLlamaAttention(nn.Module):
|
| 187 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 188 |
+
|
| 189 |
+
def __init__(self, config: DiffLlamaConfig, layer_idx: int | None = None):
|
| 190 |
+
super().__init__()
|
| 191 |
+
self.config = config
|
| 192 |
+
self.layer_idx = layer_idx
|
| 193 |
+
if layer_idx is None:
|
| 194 |
+
logger.warning_once(
|
| 195 |
+
f"Instantiating {self.__class__.__name__} without passing a `layer_idx` is not recommended and will "
|
| 196 |
+
"lead to errors during the forward call if caching is used. Please make sure to provide a `layer_idx` "
|
| 197 |
+
"when creating this class."
|
| 198 |
+
)
|
| 199 |
+
|
| 200 |
+
self.attention_dropout = config.attention_dropout
|
| 201 |
+
self.hidden_size = config.hidden_size
|
| 202 |
+
self.num_heads = config.num_attention_heads
|
| 203 |
+
self.head_dim = getattr(config, "head_dim", self.hidden_size // self.num_heads)
|
| 204 |
+
self.num_key_value_heads = config.num_key_value_heads
|
| 205 |
+
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
|
| 206 |
+
# under this are not used
|
| 207 |
+
self.max_position_embeddings = config.max_position_embeddings
|
| 208 |
+
self.is_causal = True
|
| 209 |
+
|
| 210 |
+
self.q_proj = nn.Linear(self.hidden_size, self.num_heads * self.head_dim, bias=config.attention_bias)
|
| 211 |
+
self.k_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=config.attention_bias)
|
| 212 |
+
self.v_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=config.attention_bias)
|
| 213 |
+
self.o_proj = nn.Linear(self.num_heads * self.head_dim, self.hidden_size, bias=config.attention_bias)
|
| 214 |
+
|
| 215 |
+
self.lambda_init = lambda_init_fn(layer_idx)
|
| 216 |
+
self.lambda_q1 = nn.Parameter(torch.normal(0, config.lambda_std_dev, size=(self.head_dim,)))
|
| 217 |
+
self.lambda_k1 = nn.Parameter(torch.normal(0, config.lambda_std_dev, size=(self.head_dim,)))
|
| 218 |
+
self.lambda_q2 = nn.Parameter(torch.normal(0, config.lambda_std_dev, size=(self.head_dim,)))
|
| 219 |
+
self.lambda_k2 = nn.Parameter(torch.normal(0, config.lambda_std_dev, size=(self.head_dim,)))
|
| 220 |
+
self.groupnorm = nn.RMSNorm(2 * self.head_dim, eps=config.rms_norm_eps, elementwise_affine=False)
|
| 221 |
+
|
| 222 |
+
def forward(
|
| 223 |
+
self,
|
| 224 |
+
hidden_states: torch.Tensor,
|
| 225 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 226 |
+
attention_mask: torch.Tensor | None = None,
|
| 227 |
+
position_ids: torch.LongTensor | None = None,
|
| 228 |
+
past_key_values: Cache | None = None,
|
| 229 |
+
use_cache: bool = False,
|
| 230 |
+
**kwargs,
|
| 231 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, tuple[torch.Tensor] | None]:
|
| 232 |
+
bsz, target_len, _ = hidden_states.size()
|
| 233 |
+
q_len = target_len
|
| 234 |
+
|
| 235 |
+
query_states = self.q_proj(hidden_states)
|
| 236 |
+
key_states = self.k_proj(hidden_states)
|
| 237 |
+
value_states = self.v_proj(hidden_states)
|
| 238 |
+
|
| 239 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 240 |
+
key_states = key_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 241 |
+
value_states = value_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 242 |
+
|
| 243 |
+
cos, sin = position_embeddings
|
| 244 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 245 |
+
|
| 246 |
+
if past_key_values is not None:
|
| 247 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 248 |
+
|
| 249 |
+
key_states = repeat_kv(key_states, self.num_key_value_groups)
|
| 250 |
+
value_states = repeat_kv(value_states, self.num_key_value_groups)
|
| 251 |
+
value_states = torch.cat(torch.chunk(value_states, 2, dim=1), dim=-1)
|
| 252 |
+
value_states = value_states.repeat(1, 2, 1, 1)
|
| 253 |
+
|
| 254 |
+
attn_weights = torch.matmul(query_states, key_states.transpose(2, 3)) / math.sqrt(self.head_dim)
|
| 255 |
+
|
| 256 |
+
if attention_mask is not None:
|
| 257 |
+
attn_weights = attn_weights + attention_mask
|
| 258 |
+
|
| 259 |
+
# upcast attention to fp32
|
| 260 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query_states.dtype)
|
| 261 |
+
attn_weights = nn.functional.dropout(attn_weights, p=self.attention_dropout, training=self.training)
|
| 262 |
+
lambda_1 = torch.exp(torch.sum(self.lambda_q1 * self.lambda_k1, dim=-1, dtype=torch.float32)).to(
|
| 263 |
+
query_states.dtype
|
| 264 |
+
)
|
| 265 |
+
lambda_2 = torch.exp(torch.sum(self.lambda_q2 * self.lambda_k2, dim=-1, dtype=torch.float32)).to(
|
| 266 |
+
query_states.dtype
|
| 267 |
+
)
|
| 268 |
+
lambda_full = lambda_1 - lambda_2 + self.lambda_init
|
| 269 |
+
|
| 270 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 271 |
+
attn_output1, attn_output2 = torch.chunk(attn_output, 2, dim=1)
|
| 272 |
+
|
| 273 |
+
attn_output = attn_output1 - lambda_full * attn_output2
|
| 274 |
+
attn_output = (1 - self.lambda_init) * self.groupnorm(attn_output)
|
| 275 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 276 |
+
attn_output = attn_output.reshape(bsz, q_len, -1)
|
| 277 |
+
attn_output = self.o_proj(attn_output)
|
| 278 |
+
return attn_output, attn_weights
|
| 279 |
+
|
| 280 |
+
|
| 281 |
+
class DiffLlamaFlashAttention2(DiffLlamaAttention):
|
| 282 |
+
"""
|
| 283 |
+
DiffLlama flash attention module. This module inherits from `DiffLlamaAttention` as the weights of the module stays
|
| 284 |
+
untouched. The only required change would be on the forward pass where it needs to correctly call the public API of
|
| 285 |
+
flash attention and deal with padding tokens in case the input contains any of them.
|
| 286 |
+
"""
|
| 287 |
+
|
| 288 |
+
def __init__(self, *args, **kwargs):
|
| 289 |
+
super().__init__(*args, **kwargs)
|
| 290 |
+
|
| 291 |
+
# TODO: Should be removed once Flash Attention for RoCm is bumped to 2.1.
|
| 292 |
+
# 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.
|
| 293 |
+
# 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).
|
| 294 |
+
self._flash_attn_uses_top_left_mask = flash_attn_supports_top_left_mask()
|
| 295 |
+
|
| 296 |
+
def forward(
|
| 297 |
+
self,
|
| 298 |
+
hidden_states: torch.Tensor,
|
| 299 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 300 |
+
attention_mask: torch.LongTensor | None = None,
|
| 301 |
+
position_ids: torch.LongTensor | None = None,
|
| 302 |
+
past_key_values: Cache | None = None,
|
| 303 |
+
use_cache: bool = False,
|
| 304 |
+
) -> tuple[torch.Tensor, None]:
|
| 305 |
+
if isinstance(past_key_values, StaticCache):
|
| 306 |
+
raise ValueError(
|
| 307 |
+
"`static` cache implementation is not compatible with `attn_implementation==flash_attention_2` "
|
| 308 |
+
"make sure to use `sdpa` in the mean time, and open an issue at https://github.com/huggingface/transformers"
|
| 309 |
+
)
|
| 310 |
+
|
| 311 |
+
bsz, q_len, _ = hidden_states.size()
|
| 312 |
+
|
| 313 |
+
query_states = self.q_proj(hidden_states)
|
| 314 |
+
key_states = self.k_proj(hidden_states)
|
| 315 |
+
value_states = self.v_proj(hidden_states)
|
| 316 |
+
|
| 317 |
+
# Flash attention requires the input to have the shape
|
| 318 |
+
# batch_size x seq_length x head_dim x hidden_dim
|
| 319 |
+
# therefore we just need to keep the original shape
|
| 320 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 321 |
+
key_states = key_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 322 |
+
value_states = value_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 323 |
+
|
| 324 |
+
cos, sin = position_embeddings
|
| 325 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 326 |
+
|
| 327 |
+
if past_key_values is not None:
|
| 328 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 329 |
+
|
| 330 |
+
# TODO: These transpose are quite inefficient but Flash Attention requires the layout [batch_size, sequence_length, num_heads, head_dim]. We would need to refactor the KV cache
|
| 331 |
+
# to be able to avoid many of these transpose/reshape/view.
|
| 332 |
+
query_states = query_states.transpose(1, 2)
|
| 333 |
+
key_states = key_states.transpose(1, 2)
|
| 334 |
+
value_states = value_states.transpose(1, 2)
|
| 335 |
+
|
| 336 |
+
dropout_rate = self.attention_dropout if self.training else 0.0
|
| 337 |
+
|
| 338 |
+
# In PEFT, usually we cast the layer norms in float32 for training stability reasons
|
| 339 |
+
# therefore the input hidden states gets silently casted in float32. Hence, we need
|
| 340 |
+
# cast them back in the correct dtype just to be sure everything works as expected.
|
| 341 |
+
# This might slowdown training & inference so it is recommended to not cast the LayerNorms
|
| 342 |
+
# in fp32. (DiffLlamaRMSNorm handles it correctly)
|
| 343 |
+
|
| 344 |
+
input_dtype = query_states.dtype
|
| 345 |
+
device_type = query_states.device.type if query_states.device.type != "mps" else "cpu"
|
| 346 |
+
if input_dtype == torch.float32:
|
| 347 |
+
if torch.is_autocast_enabled(device_type):
|
| 348 |
+
target_dtype = torch.get_autocast_dtype(device_type)
|
| 349 |
+
# Handle the case where the model is quantized
|
| 350 |
+
elif hasattr(self.config, "_is_quantized"):
|
| 351 |
+
target_dtype = self.config.dtype
|
| 352 |
+
else:
|
| 353 |
+
target_dtype = self.q_proj.weight.dtype
|
| 354 |
+
|
| 355 |
+
logger.warning_once(
|
| 356 |
+
f"The input hidden states seems to be silently casted in float32, this might be related to"
|
| 357 |
+
f" the fact you have upcasted embedding or layer norm layers in float32. We will cast back the input in"
|
| 358 |
+
f" {target_dtype}."
|
| 359 |
+
)
|
| 360 |
+
|
| 361 |
+
query_states = query_states.to(target_dtype)
|
| 362 |
+
key_states = key_states.to(target_dtype)
|
| 363 |
+
value_states = value_states.to(target_dtype)
|
| 364 |
+
|
| 365 |
+
value_states1, value_states2 = torch.chunk(value_states, 2, dim=2)
|
| 366 |
+
value_states1 = value_states1.repeat(1, 1, 2, 1)
|
| 367 |
+
value_states2 = value_states2.repeat(1, 1, 2, 1)
|
| 368 |
+
|
| 369 |
+
attn_output1 = _flash_attention_forward(
|
| 370 |
+
query_states,
|
| 371 |
+
key_states,
|
| 372 |
+
value_states1,
|
| 373 |
+
attention_mask,
|
| 374 |
+
q_len,
|
| 375 |
+
position_ids=position_ids,
|
| 376 |
+
dropout=dropout_rate,
|
| 377 |
+
sliding_window=getattr(self, "sliding_window", None),
|
| 378 |
+
use_top_left_mask=self._flash_attn_uses_top_left_mask,
|
| 379 |
+
is_causal=self.is_causal,
|
| 380 |
+
)
|
| 381 |
+
|
| 382 |
+
attn_output2 = _flash_attention_forward(
|
| 383 |
+
query_states,
|
| 384 |
+
key_states,
|
| 385 |
+
value_states2,
|
| 386 |
+
attention_mask,
|
| 387 |
+
q_len,
|
| 388 |
+
position_ids=position_ids,
|
| 389 |
+
dropout=dropout_rate,
|
| 390 |
+
sliding_window=getattr(self, "sliding_window", None),
|
| 391 |
+
use_top_left_mask=self._flash_attn_uses_top_left_mask,
|
| 392 |
+
is_causal=self.is_causal,
|
| 393 |
+
)
|
| 394 |
+
|
| 395 |
+
attn_output = torch.cat([attn_output1, attn_output2], dim=-1)
|
| 396 |
+
attn_output1, attn_output2 = torch.chunk(attn_output, 2, dim=2)
|
| 397 |
+
|
| 398 |
+
lambda_1 = torch.exp(torch.sum(self.lambda_q1 * self.lambda_k1, dim=-1, dtype=torch.float32)).to(
|
| 399 |
+
query_states.dtype
|
| 400 |
+
)
|
| 401 |
+
lambda_2 = torch.exp(torch.sum(self.lambda_q2 * self.lambda_k2, dim=-1, dtype=torch.float32)).to(
|
| 402 |
+
query_states.dtype
|
| 403 |
+
)
|
| 404 |
+
lambda_full = lambda_1 - lambda_2 + self.lambda_init
|
| 405 |
+
|
| 406 |
+
attn_output = attn_output1 - lambda_full * attn_output2
|
| 407 |
+
attn_output = (1 - self.lambda_init) * self.groupnorm(attn_output)
|
| 408 |
+
attn_output = attn_output.reshape(bsz, q_len, -1).contiguous()
|
| 409 |
+
attn_output = self.o_proj(attn_output)
|
| 410 |
+
return attn_output, None
|
| 411 |
+
|
| 412 |
+
|
| 413 |
+
class DiffLlamaSdpaAttention(DiffLlamaAttention):
|
| 414 |
+
"""
|
| 415 |
+
DiffLlama attention module using torch.nn.functional.scaled_dot_product_attention. This module inherits from
|
| 416 |
+
`DiffLlamaAttention` as the weights of the module stays untouched. The only changes are on the forward pass to adapt to
|
| 417 |
+
SDPA API.
|
| 418 |
+
"""
|
| 419 |
+
|
| 420 |
+
# Adapted from DiffLlamaAttention.forward
|
| 421 |
+
def forward(
|
| 422 |
+
self,
|
| 423 |
+
hidden_states: torch.Tensor,
|
| 424 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 425 |
+
attention_mask: torch.Tensor | None = None,
|
| 426 |
+
position_ids: torch.LongTensor | None = None,
|
| 427 |
+
past_key_values: Cache | None = None,
|
| 428 |
+
use_cache: bool = False,
|
| 429 |
+
**kwargs,
|
| 430 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, tuple[torch.Tensor] | None]:
|
| 431 |
+
bsz, q_len, _ = hidden_states.size()
|
| 432 |
+
|
| 433 |
+
query_states = self.q_proj(hidden_states)
|
| 434 |
+
key_states = self.k_proj(hidden_states)
|
| 435 |
+
value_states = self.v_proj(hidden_states)
|
| 436 |
+
|
| 437 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 438 |
+
key_states = key_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 439 |
+
value_states = value_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 440 |
+
|
| 441 |
+
cos, sin = position_embeddings
|
| 442 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 443 |
+
|
| 444 |
+
if past_key_values is not None:
|
| 445 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 446 |
+
|
| 447 |
+
key_states = repeat_kv(key_states, self.num_key_value_groups)
|
| 448 |
+
value_states = repeat_kv(value_states, self.num_key_value_groups)
|
| 449 |
+
value_states = torch.cat(torch.chunk(value_states, 2, dim=1), dim=-1)
|
| 450 |
+
value_states = value_states.repeat(1, 2, 1, 1)
|
| 451 |
+
|
| 452 |
+
causal_mask = attention_mask
|
| 453 |
+
if attention_mask is not None:
|
| 454 |
+
causal_mask = causal_mask[:, :, :, : key_states.shape[-2]]
|
| 455 |
+
|
| 456 |
+
# We dispatch to SDPA's Flash Attention or Efficient kernels via this `is_causal` if statement instead of an inline conditional assignment
|
| 457 |
+
# in SDPA to support both torch.compile's dynamic shapes and full graph options. An inline conditional prevents dynamic shapes from compiling.
|
| 458 |
+
is_causal = causal_mask is None and q_len > 1
|
| 459 |
+
|
| 460 |
+
attn_output = torch.nn.functional.scaled_dot_product_attention(
|
| 461 |
+
query_states,
|
| 462 |
+
key_states,
|
| 463 |
+
value_states,
|
| 464 |
+
attn_mask=causal_mask,
|
| 465 |
+
dropout_p=self.attention_dropout if self.training else 0.0,
|
| 466 |
+
is_causal=is_causal,
|
| 467 |
+
)
|
| 468 |
+
|
| 469 |
+
attn_output1, attn_output2 = torch.chunk(attn_output, 2, dim=1)
|
| 470 |
+
|
| 471 |
+
lambda_1 = torch.exp(torch.sum(self.lambda_q1 * self.lambda_k1, dim=-1, dtype=torch.float32)).to(
|
| 472 |
+
query_states.dtype
|
| 473 |
+
)
|
| 474 |
+
lambda_2 = torch.exp(torch.sum(self.lambda_q2 * self.lambda_k2, dim=-1, dtype=torch.float32)).to(
|
| 475 |
+
query_states.dtype
|
| 476 |
+
)
|
| 477 |
+
lambda_full = lambda_1 - lambda_2 + self.lambda_init
|
| 478 |
+
|
| 479 |
+
attn_output = attn_output1 - lambda_full * attn_output2
|
| 480 |
+
attn_output = (1 - self.lambda_init) * self.groupnorm(attn_output)
|
| 481 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 482 |
+
attn_output = attn_output.view(bsz, q_len, -1)
|
| 483 |
+
attn_output = self.o_proj(attn_output)
|
| 484 |
+
return attn_output, None
|
| 485 |
+
|
| 486 |
+
|
| 487 |
+
@use_kernel_forward_from_hub("RMSNorm")
|
| 488 |
+
class DiffLlamaRMSNorm(nn.Module):
|
| 489 |
+
def __init__(self, hidden_size, eps: float = 1e-6) -> None:
|
| 490 |
+
"""
|
| 491 |
+
DiffLlamaRMSNorm is equivalent to T5LayerNorm
|
| 492 |
+
"""
|
| 493 |
+
super().__init__()
|
| 494 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
| 495 |
+
self.variance_epsilon = eps
|
| 496 |
+
|
| 497 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 498 |
+
input_dtype = hidden_states.dtype
|
| 499 |
+
hidden_states = hidden_states.to(torch.float32)
|
| 500 |
+
variance = hidden_states.pow(2).mean(-1, keepdim=True)
|
| 501 |
+
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
|
| 502 |
+
return self.weight * hidden_states.to(input_dtype)
|
| 503 |
+
|
| 504 |
+
def extra_repr(self):
|
| 505 |
+
return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
|
| 506 |
+
|
| 507 |
+
|
| 508 |
+
DIFFLLAMA_ATTENTION_CLASSES = {
|
| 509 |
+
"eager": DiffLlamaAttention,
|
| 510 |
+
"flash_attention_2": DiffLlamaFlashAttention2,
|
| 511 |
+
"sdpa": DiffLlamaSdpaAttention,
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
|
| 515 |
+
class DiffLlamaDecoderLayer(GradientCheckpointingLayer):
|
| 516 |
+
def __init__(self, config: DiffLlamaConfig, layer_idx: int):
|
| 517 |
+
super().__init__()
|
| 518 |
+
self.hidden_size = config.hidden_size
|
| 519 |
+
|
| 520 |
+
self.self_attn = DIFFLLAMA_ATTENTION_CLASSES[config._attn_implementation](config=config, layer_idx=layer_idx)
|
| 521 |
+
|
| 522 |
+
self.mlp = DiffLlamaMLP(config)
|
| 523 |
+
self.input_layernorm = DiffLlamaRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 524 |
+
self.post_attention_layernorm = DiffLlamaRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 525 |
+
|
| 526 |
+
def forward(
|
| 527 |
+
self,
|
| 528 |
+
hidden_states: torch.Tensor,
|
| 529 |
+
attention_mask: torch.Tensor | None = None,
|
| 530 |
+
position_ids: torch.LongTensor | None = None,
|
| 531 |
+
past_key_values: Cache | None = None,
|
| 532 |
+
use_cache: bool | None = False,
|
| 533 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 534 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 535 |
+
) -> torch.Tensor:
|
| 536 |
+
residual = hidden_states
|
| 537 |
+
hidden_states = self.input_layernorm(hidden_states)
|
| 538 |
+
# Self Attention
|
| 539 |
+
hidden_states, _ = self.self_attn(
|
| 540 |
+
hidden_states=hidden_states,
|
| 541 |
+
attention_mask=attention_mask,
|
| 542 |
+
position_ids=position_ids,
|
| 543 |
+
past_key_values=past_key_values,
|
| 544 |
+
use_cache=use_cache,
|
| 545 |
+
position_embeddings=position_embeddings,
|
| 546 |
+
**kwargs,
|
| 547 |
+
)
|
| 548 |
+
hidden_states = residual + hidden_states
|
| 549 |
+
|
| 550 |
+
# Fully Connected
|
| 551 |
+
residual = hidden_states
|
| 552 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 553 |
+
hidden_states = self.mlp(hidden_states)
|
| 554 |
+
hidden_states = residual + hidden_states
|
| 555 |
+
return hidden_states
|
| 556 |
+
|
| 557 |
+
|
| 558 |
+
@auto_docstring
|
| 559 |
+
class DiffLlamaPreTrainedModel(PreTrainedModel):
|
| 560 |
+
config: DiffLlamaConfig
|
| 561 |
+
base_model_prefix = "model"
|
| 562 |
+
supports_gradient_checkpointing = True
|
| 563 |
+
_no_split_modules = ["DiffLlamaDecoderLayer"]
|
| 564 |
+
_skip_keys_device_placement = ["past_key_values"]
|
| 565 |
+
_supports_flash_attn = True
|
| 566 |
+
_supports_sdpa = True
|
| 567 |
+
_supports_flex_attn = False
|
| 568 |
+
|
| 569 |
+
_can_compile_fullgraph = True
|
| 570 |
+
_supports_attention_backend = False
|
| 571 |
+
_can_record_outputs = {
|
| 572 |
+
"hidden_states": DiffLlamaDecoderLayer,
|
| 573 |
+
"attentions": DiffLlamaAttention,
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
@torch.no_grad()
|
| 577 |
+
def _init_weights(self, module):
|
| 578 |
+
super()._init_weights(module)
|
| 579 |
+
if isinstance(module, DiffLlamaAttention):
|
| 580 |
+
init.normal_(module.lambda_q1, 0, self.config.lambda_std_dev)
|
| 581 |
+
init.normal_(module.lambda_k1, 0, self.config.lambda_std_dev)
|
| 582 |
+
init.normal_(module.lambda_q2, 0, self.config.lambda_std_dev)
|
| 583 |
+
init.normal_(module.lambda_k2, 0, self.config.lambda_std_dev)
|
| 584 |
+
|
| 585 |
+
|
| 586 |
+
@auto_docstring
|
| 587 |
+
class DiffLlamaModel(DiffLlamaPreTrainedModel):
|
| 588 |
+
def __init__(self, config: DiffLlamaConfig):
|
| 589 |
+
super().__init__(config)
|
| 590 |
+
self.padding_idx = config.pad_token_id
|
| 591 |
+
self.vocab_size = config.vocab_size
|
| 592 |
+
|
| 593 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
|
| 594 |
+
self.layers = nn.ModuleList(
|
| 595 |
+
[DiffLlamaDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 596 |
+
)
|
| 597 |
+
self.norm = DiffLlamaRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 598 |
+
self.rotary_emb = DiffLlamaRotaryEmbedding(config=config)
|
| 599 |
+
self.gradient_checkpointing = False
|
| 600 |
+
|
| 601 |
+
# Initialize weights and apply final processing
|
| 602 |
+
self.post_init()
|
| 603 |
+
|
| 604 |
+
@merge_with_config_defaults
|
| 605 |
+
@capture_outputs
|
| 606 |
+
@auto_docstring
|
| 607 |
+
def forward(
|
| 608 |
+
self,
|
| 609 |
+
input_ids: torch.LongTensor | None = None,
|
| 610 |
+
attention_mask: torch.Tensor | None = None,
|
| 611 |
+
position_ids: torch.LongTensor | None = None,
|
| 612 |
+
past_key_values: Cache | None = None,
|
| 613 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 614 |
+
use_cache: bool | None = None,
|
| 615 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 616 |
+
) -> BaseModelOutputWithPast:
|
| 617 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 618 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 619 |
+
|
| 620 |
+
if inputs_embeds is None:
|
| 621 |
+
inputs_embeds: torch.Tensor = self.embed_tokens(input_ids)
|
| 622 |
+
|
| 623 |
+
if use_cache and past_key_values is None:
|
| 624 |
+
past_key_values = DynamicCache(config=self.config)
|
| 625 |
+
|
| 626 |
+
if position_ids is None:
|
| 627 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 628 |
+
position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
|
| 629 |
+
position_ids = position_ids.unsqueeze(0)
|
| 630 |
+
|
| 631 |
+
causal_mask = create_causal_mask(
|
| 632 |
+
config=self.config,
|
| 633 |
+
inputs_embeds=inputs_embeds,
|
| 634 |
+
attention_mask=attention_mask,
|
| 635 |
+
past_key_values=past_key_values,
|
| 636 |
+
position_ids=position_ids,
|
| 637 |
+
)
|
| 638 |
+
|
| 639 |
+
hidden_states = inputs_embeds
|
| 640 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids=position_ids)
|
| 641 |
+
|
| 642 |
+
for decoder_layer in self.layers[: self.config.num_hidden_layers]:
|
| 643 |
+
hidden_states = decoder_layer(
|
| 644 |
+
hidden_states,
|
| 645 |
+
attention_mask=causal_mask,
|
| 646 |
+
position_embeddings=position_embeddings,
|
| 647 |
+
position_ids=position_ids,
|
| 648 |
+
past_key_values=past_key_values,
|
| 649 |
+
use_cache=use_cache,
|
| 650 |
+
**kwargs,
|
| 651 |
+
)
|
| 652 |
+
|
| 653 |
+
hidden_states = self.norm(hidden_states)
|
| 654 |
+
return BaseModelOutputWithPast(
|
| 655 |
+
last_hidden_state=hidden_states,
|
| 656 |
+
past_key_values=past_key_values,
|
| 657 |
+
)
|
| 658 |
+
|
| 659 |
+
|
| 660 |
+
@auto_docstring
|
| 661 |
+
class DiffLlamaForCausalLM(DiffLlamaPreTrainedModel, GenerationMixin):
|
| 662 |
+
_tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
|
| 663 |
+
_tp_plan = {"lm_head": "colwise_gather_output"}
|
| 664 |
+
_pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
|
| 665 |
+
|
| 666 |
+
def __init__(self, config):
|
| 667 |
+
super().__init__(config)
|
| 668 |
+
self.model = DiffLlamaModel(config)
|
| 669 |
+
self.vocab_size = config.vocab_size
|
| 670 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 671 |
+
|
| 672 |
+
# Initialize weights and apply final processing
|
| 673 |
+
self.post_init()
|
| 674 |
+
|
| 675 |
+
@can_return_tuple
|
| 676 |
+
@auto_docstring
|
| 677 |
+
def forward(
|
| 678 |
+
self,
|
| 679 |
+
input_ids: torch.LongTensor | None = None,
|
| 680 |
+
attention_mask: torch.Tensor | None = None,
|
| 681 |
+
position_ids: torch.LongTensor | None = None,
|
| 682 |
+
past_key_values: Cache | None = None,
|
| 683 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 684 |
+
labels: torch.LongTensor | None = None,
|
| 685 |
+
use_cache: bool | None = None,
|
| 686 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 687 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 688 |
+
) -> CausalLMOutputWithPast:
|
| 689 |
+
r"""
|
| 690 |
+
Example:
|
| 691 |
+
|
| 692 |
+
```python
|
| 693 |
+
>>> from transformers import AutoTokenizer, DiffLlamaForCausalLM
|
| 694 |
+
|
| 695 |
+
>>> model = DiffLlamaForCausalLM.from_pretrained("google/diffllama-7b")
|
| 696 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("google/diffllama-7b")
|
| 697 |
+
|
| 698 |
+
>>> prompt = "What is your favorite condiment?"
|
| 699 |
+
>>> inputs = tokenizer(prompt, return_tensors="pt")
|
| 700 |
+
|
| 701 |
+
>>> # Generate
|
| 702 |
+
>>> generate_ids = model.generate(inputs.input_ids, max_length=30)
|
| 703 |
+
>>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
|
| 704 |
+
"What is your favorite condiment?"
|
| 705 |
+
```"""
|
| 706 |
+
outputs: BaseModelOutputWithPast = self.model(
|
| 707 |
+
input_ids=input_ids,
|
| 708 |
+
attention_mask=attention_mask,
|
| 709 |
+
position_ids=position_ids,
|
| 710 |
+
past_key_values=past_key_values,
|
| 711 |
+
inputs_embeds=inputs_embeds,
|
| 712 |
+
use_cache=use_cache,
|
| 713 |
+
**kwargs,
|
| 714 |
+
)
|
| 715 |
+
|
| 716 |
+
hidden_states = outputs.last_hidden_state
|
| 717 |
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
| 718 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 719 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
| 720 |
+
|
| 721 |
+
loss = None
|
| 722 |
+
if labels is not None:
|
| 723 |
+
loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs)
|
| 724 |
+
|
| 725 |
+
return CausalLMOutputWithPast(
|
| 726 |
+
loss=loss,
|
| 727 |
+
logits=logits,
|
| 728 |
+
past_key_values=outputs.past_key_values,
|
| 729 |
+
hidden_states=outputs.hidden_states,
|
| 730 |
+
attentions=outputs.attentions,
|
| 731 |
+
)
|
| 732 |
+
|
| 733 |
+
|
| 734 |
+
class DiffLlamaForSequenceClassification(GenericForSequenceClassification, DiffLlamaPreTrainedModel):
|
| 735 |
+
pass
|
| 736 |
+
|
| 737 |
+
|
| 738 |
+
class DiffLlamaForQuestionAnswering(GenericForQuestionAnswering, DiffLlamaPreTrainedModel):
|
| 739 |
+
base_model_prefix = "transformer" # For BC, where `transformer` was used instead of `model`
|
| 740 |
+
|
| 741 |
+
|
| 742 |
+
class DiffLlamaForTokenClassification(GenericForTokenClassification, DiffLlamaPreTrainedModel):
|
| 743 |
+
pass
|
| 744 |
+
|
| 745 |
+
|
| 746 |
+
__all__ = [
|
| 747 |
+
"DiffLlamaPreTrainedModel",
|
| 748 |
+
"DiffLlamaModel",
|
| 749 |
+
"DiffLlamaForCausalLM",
|
| 750 |
+
"DiffLlamaForSequenceClassification",
|
| 751 |
+
"DiffLlamaForQuestionAnswering",
|
| 752 |
+
"DiffLlamaForTokenClassification",
|
| 753 |
+
]
|
third_party/transformers/src/transformers/models/diffllama/modular_diffllama.py
ADDED
|
@@ -0,0 +1,417 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 weak-kajuma and the HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# This code is based on Llama implementations in this library and Microsoft's
|
| 4 |
+
# Differential Transformer implementations.
|
| 5 |
+
|
| 6 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 7 |
+
# you may not use this file except in compliance with the License.
|
| 8 |
+
# You may obtain a copy of the License at
|
| 9 |
+
#
|
| 10 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 11 |
+
#
|
| 12 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 13 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 14 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 15 |
+
# See the License for the specific language governing permissions and
|
| 16 |
+
# limitations under the License.
|
| 17 |
+
import math
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
from torch import nn
|
| 21 |
+
|
| 22 |
+
from ... import initialization as init
|
| 23 |
+
from ...cache_utils import Cache, StaticCache
|
| 24 |
+
from ...modeling_flash_attention_utils import _flash_attention_forward, flash_attn_supports_top_left_mask
|
| 25 |
+
from ...modeling_utils import PreTrainedModel
|
| 26 |
+
from ...utils import logging
|
| 27 |
+
from ..gemma.modeling_gemma import GemmaForCausalLM
|
| 28 |
+
from ..llama.modeling_llama import (
|
| 29 |
+
LlamaDecoderLayer,
|
| 30 |
+
LlamaForQuestionAnswering,
|
| 31 |
+
LlamaForSequenceClassification,
|
| 32 |
+
LlamaForTokenClassification,
|
| 33 |
+
LlamaModel,
|
| 34 |
+
LlamaPreTrainedModel,
|
| 35 |
+
LlamaRotaryEmbedding,
|
| 36 |
+
apply_rotary_pos_emb,
|
| 37 |
+
repeat_kv,
|
| 38 |
+
)
|
| 39 |
+
from ..mistral.modeling_mistral import MistralMLP
|
| 40 |
+
from .configuration_diffllama import DiffLlamaConfig
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
logger = logging.get_logger(__name__)
|
| 44 |
+
|
| 45 |
+
_CHECKPOINT_FOR_DOC = "kajuma/DiffLlama-0.3B-handcut"
|
| 46 |
+
_CONFIG_FOR_DOC = "DiffLlamaConfig"
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
class DiffLlamaMLP(MistralMLP):
|
| 50 |
+
pass
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def lambda_init_fn(layer_idx):
|
| 54 |
+
return 0.8 - 0.6 * math.exp(-0.3 * layer_idx)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class DiffLlamaRotaryEmbedding(LlamaRotaryEmbedding):
|
| 58 |
+
pass
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
class DiffLlamaAttention(nn.Module):
|
| 62 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 63 |
+
|
| 64 |
+
def __init__(self, config: DiffLlamaConfig, layer_idx: int | None = None):
|
| 65 |
+
super().__init__()
|
| 66 |
+
self.config = config
|
| 67 |
+
self.layer_idx = layer_idx
|
| 68 |
+
if layer_idx is None:
|
| 69 |
+
logger.warning_once(
|
| 70 |
+
f"Instantiating {self.__class__.__name__} without passing a `layer_idx` is not recommended and will "
|
| 71 |
+
"lead to errors during the forward call if caching is used. Please make sure to provide a `layer_idx` "
|
| 72 |
+
"when creating this class."
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
self.attention_dropout = config.attention_dropout
|
| 76 |
+
self.hidden_size = config.hidden_size
|
| 77 |
+
self.num_heads = config.num_attention_heads
|
| 78 |
+
self.head_dim = getattr(config, "head_dim", self.hidden_size // self.num_heads)
|
| 79 |
+
self.num_key_value_heads = config.num_key_value_heads
|
| 80 |
+
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
|
| 81 |
+
# under this are not used
|
| 82 |
+
self.max_position_embeddings = config.max_position_embeddings
|
| 83 |
+
self.is_causal = True
|
| 84 |
+
|
| 85 |
+
self.q_proj = nn.Linear(self.hidden_size, self.num_heads * self.head_dim, bias=config.attention_bias)
|
| 86 |
+
self.k_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=config.attention_bias)
|
| 87 |
+
self.v_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=config.attention_bias)
|
| 88 |
+
self.o_proj = nn.Linear(self.num_heads * self.head_dim, self.hidden_size, bias=config.attention_bias)
|
| 89 |
+
|
| 90 |
+
self.lambda_init = lambda_init_fn(layer_idx)
|
| 91 |
+
self.lambda_q1 = nn.Parameter(torch.normal(0, config.lambda_std_dev, size=(self.head_dim,)))
|
| 92 |
+
self.lambda_k1 = nn.Parameter(torch.normal(0, config.lambda_std_dev, size=(self.head_dim,)))
|
| 93 |
+
self.lambda_q2 = nn.Parameter(torch.normal(0, config.lambda_std_dev, size=(self.head_dim,)))
|
| 94 |
+
self.lambda_k2 = nn.Parameter(torch.normal(0, config.lambda_std_dev, size=(self.head_dim,)))
|
| 95 |
+
self.groupnorm = nn.RMSNorm(2 * self.head_dim, eps=config.rms_norm_eps, elementwise_affine=False)
|
| 96 |
+
|
| 97 |
+
def forward(
|
| 98 |
+
self,
|
| 99 |
+
hidden_states: torch.Tensor,
|
| 100 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 101 |
+
attention_mask: torch.Tensor | None = None,
|
| 102 |
+
position_ids: torch.LongTensor | None = None,
|
| 103 |
+
past_key_values: Cache | None = None,
|
| 104 |
+
use_cache: bool = False,
|
| 105 |
+
**kwargs,
|
| 106 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, tuple[torch.Tensor] | None]:
|
| 107 |
+
bsz, target_len, _ = hidden_states.size()
|
| 108 |
+
q_len = target_len
|
| 109 |
+
|
| 110 |
+
query_states = self.q_proj(hidden_states)
|
| 111 |
+
key_states = self.k_proj(hidden_states)
|
| 112 |
+
value_states = self.v_proj(hidden_states)
|
| 113 |
+
|
| 114 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 115 |
+
key_states = key_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 116 |
+
value_states = value_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 117 |
+
|
| 118 |
+
cos, sin = position_embeddings
|
| 119 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 120 |
+
|
| 121 |
+
if past_key_values is not None:
|
| 122 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 123 |
+
|
| 124 |
+
key_states = repeat_kv(key_states, self.num_key_value_groups)
|
| 125 |
+
value_states = repeat_kv(value_states, self.num_key_value_groups)
|
| 126 |
+
value_states = torch.cat(torch.chunk(value_states, 2, dim=1), dim=-1)
|
| 127 |
+
value_states = value_states.repeat(1, 2, 1, 1)
|
| 128 |
+
|
| 129 |
+
attn_weights = torch.matmul(query_states, key_states.transpose(2, 3)) / math.sqrt(self.head_dim)
|
| 130 |
+
|
| 131 |
+
if attention_mask is not None:
|
| 132 |
+
attn_weights = attn_weights + attention_mask
|
| 133 |
+
|
| 134 |
+
# upcast attention to fp32
|
| 135 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query_states.dtype)
|
| 136 |
+
attn_weights = nn.functional.dropout(attn_weights, p=self.attention_dropout, training=self.training)
|
| 137 |
+
lambda_1 = torch.exp(torch.sum(self.lambda_q1 * self.lambda_k1, dim=-1, dtype=torch.float32)).to(
|
| 138 |
+
query_states.dtype
|
| 139 |
+
)
|
| 140 |
+
lambda_2 = torch.exp(torch.sum(self.lambda_q2 * self.lambda_k2, dim=-1, dtype=torch.float32)).to(
|
| 141 |
+
query_states.dtype
|
| 142 |
+
)
|
| 143 |
+
lambda_full = lambda_1 - lambda_2 + self.lambda_init
|
| 144 |
+
|
| 145 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 146 |
+
attn_output1, attn_output2 = torch.chunk(attn_output, 2, dim=1)
|
| 147 |
+
|
| 148 |
+
attn_output = attn_output1 - lambda_full * attn_output2
|
| 149 |
+
attn_output = (1 - self.lambda_init) * self.groupnorm(attn_output)
|
| 150 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 151 |
+
attn_output = attn_output.reshape(bsz, q_len, -1)
|
| 152 |
+
attn_output = self.o_proj(attn_output)
|
| 153 |
+
return attn_output, attn_weights
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
class DiffLlamaFlashAttention2(DiffLlamaAttention):
|
| 157 |
+
"""
|
| 158 |
+
DiffLlama flash attention module. This module inherits from `DiffLlamaAttention` as the weights of the module stays
|
| 159 |
+
untouched. The only required change would be on the forward pass where it needs to correctly call the public API of
|
| 160 |
+
flash attention and deal with padding tokens in case the input contains any of them.
|
| 161 |
+
"""
|
| 162 |
+
|
| 163 |
+
def __init__(self, *args, **kwargs):
|
| 164 |
+
super().__init__(*args, **kwargs)
|
| 165 |
+
|
| 166 |
+
# TODO: Should be removed once Flash Attention for RoCm is bumped to 2.1.
|
| 167 |
+
# 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.
|
| 168 |
+
# 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).
|
| 169 |
+
self._flash_attn_uses_top_left_mask = flash_attn_supports_top_left_mask()
|
| 170 |
+
|
| 171 |
+
def forward(
|
| 172 |
+
self,
|
| 173 |
+
hidden_states: torch.Tensor,
|
| 174 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 175 |
+
attention_mask: torch.LongTensor | None = None,
|
| 176 |
+
position_ids: torch.LongTensor | None = None,
|
| 177 |
+
past_key_values: Cache | None = None,
|
| 178 |
+
use_cache: bool = False,
|
| 179 |
+
) -> tuple[torch.Tensor, None]:
|
| 180 |
+
if isinstance(past_key_values, StaticCache):
|
| 181 |
+
raise ValueError(
|
| 182 |
+
"`static` cache implementation is not compatible with `attn_implementation==flash_attention_2` "
|
| 183 |
+
"make sure to use `sdpa` in the mean time, and open an issue at https://github.com/huggingface/transformers"
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
bsz, q_len, _ = hidden_states.size()
|
| 187 |
+
|
| 188 |
+
query_states = self.q_proj(hidden_states)
|
| 189 |
+
key_states = self.k_proj(hidden_states)
|
| 190 |
+
value_states = self.v_proj(hidden_states)
|
| 191 |
+
|
| 192 |
+
# Flash attention requires the input to have the shape
|
| 193 |
+
# batch_size x seq_length x head_dim x hidden_dim
|
| 194 |
+
# therefore we just need to keep the original shape
|
| 195 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 196 |
+
key_states = key_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 197 |
+
value_states = value_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 198 |
+
|
| 199 |
+
cos, sin = position_embeddings
|
| 200 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 201 |
+
|
| 202 |
+
if past_key_values is not None:
|
| 203 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 204 |
+
|
| 205 |
+
# TODO: These transpose are quite inefficient but Flash Attention requires the layout [batch_size, sequence_length, num_heads, head_dim]. We would need to refactor the KV cache
|
| 206 |
+
# to be able to avoid many of these transpose/reshape/view.
|
| 207 |
+
query_states = query_states.transpose(1, 2)
|
| 208 |
+
key_states = key_states.transpose(1, 2)
|
| 209 |
+
value_states = value_states.transpose(1, 2)
|
| 210 |
+
|
| 211 |
+
dropout_rate = self.attention_dropout if self.training else 0.0
|
| 212 |
+
|
| 213 |
+
# In PEFT, usually we cast the layer norms in float32 for training stability reasons
|
| 214 |
+
# therefore the input hidden states gets silently casted in float32. Hence, we need
|
| 215 |
+
# cast them back in the correct dtype just to be sure everything works as expected.
|
| 216 |
+
# This might slowdown training & inference so it is recommended to not cast the LayerNorms
|
| 217 |
+
# in fp32. (DiffLlamaRMSNorm handles it correctly)
|
| 218 |
+
|
| 219 |
+
input_dtype = query_states.dtype
|
| 220 |
+
device_type = query_states.device.type if query_states.device.type != "mps" else "cpu"
|
| 221 |
+
if input_dtype == torch.float32:
|
| 222 |
+
if torch.is_autocast_enabled(device_type):
|
| 223 |
+
target_dtype = torch.get_autocast_dtype(device_type)
|
| 224 |
+
# Handle the case where the model is quantized
|
| 225 |
+
elif hasattr(self.config, "_is_quantized"):
|
| 226 |
+
target_dtype = self.config.dtype
|
| 227 |
+
else:
|
| 228 |
+
target_dtype = self.q_proj.weight.dtype
|
| 229 |
+
|
| 230 |
+
logger.warning_once(
|
| 231 |
+
f"The input hidden states seems to be silently casted in float32, this might be related to"
|
| 232 |
+
f" the fact you have upcasted embedding or layer norm layers in float32. We will cast back the input in"
|
| 233 |
+
f" {target_dtype}."
|
| 234 |
+
)
|
| 235 |
+
|
| 236 |
+
query_states = query_states.to(target_dtype)
|
| 237 |
+
key_states = key_states.to(target_dtype)
|
| 238 |
+
value_states = value_states.to(target_dtype)
|
| 239 |
+
|
| 240 |
+
value_states1, value_states2 = torch.chunk(value_states, 2, dim=2)
|
| 241 |
+
value_states1 = value_states1.repeat(1, 1, 2, 1)
|
| 242 |
+
value_states2 = value_states2.repeat(1, 1, 2, 1)
|
| 243 |
+
|
| 244 |
+
attn_output1 = _flash_attention_forward(
|
| 245 |
+
query_states,
|
| 246 |
+
key_states,
|
| 247 |
+
value_states1,
|
| 248 |
+
attention_mask,
|
| 249 |
+
q_len,
|
| 250 |
+
position_ids=position_ids,
|
| 251 |
+
dropout=dropout_rate,
|
| 252 |
+
sliding_window=getattr(self, "sliding_window", None),
|
| 253 |
+
use_top_left_mask=self._flash_attn_uses_top_left_mask,
|
| 254 |
+
is_causal=self.is_causal,
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
attn_output2 = _flash_attention_forward(
|
| 258 |
+
query_states,
|
| 259 |
+
key_states,
|
| 260 |
+
value_states2,
|
| 261 |
+
attention_mask,
|
| 262 |
+
q_len,
|
| 263 |
+
position_ids=position_ids,
|
| 264 |
+
dropout=dropout_rate,
|
| 265 |
+
sliding_window=getattr(self, "sliding_window", None),
|
| 266 |
+
use_top_left_mask=self._flash_attn_uses_top_left_mask,
|
| 267 |
+
is_causal=self.is_causal,
|
| 268 |
+
)
|
| 269 |
+
|
| 270 |
+
attn_output = torch.cat([attn_output1, attn_output2], dim=-1)
|
| 271 |
+
attn_output1, attn_output2 = torch.chunk(attn_output, 2, dim=2)
|
| 272 |
+
|
| 273 |
+
lambda_1 = torch.exp(torch.sum(self.lambda_q1 * self.lambda_k1, dim=-1, dtype=torch.float32)).to(
|
| 274 |
+
query_states.dtype
|
| 275 |
+
)
|
| 276 |
+
lambda_2 = torch.exp(torch.sum(self.lambda_q2 * self.lambda_k2, dim=-1, dtype=torch.float32)).to(
|
| 277 |
+
query_states.dtype
|
| 278 |
+
)
|
| 279 |
+
lambda_full = lambda_1 - lambda_2 + self.lambda_init
|
| 280 |
+
|
| 281 |
+
attn_output = attn_output1 - lambda_full * attn_output2
|
| 282 |
+
attn_output = (1 - self.lambda_init) * self.groupnorm(attn_output)
|
| 283 |
+
attn_output = attn_output.reshape(bsz, q_len, -1).contiguous()
|
| 284 |
+
attn_output = self.o_proj(attn_output)
|
| 285 |
+
return attn_output, None
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
class DiffLlamaSdpaAttention(DiffLlamaAttention):
|
| 289 |
+
"""
|
| 290 |
+
DiffLlama attention module using torch.nn.functional.scaled_dot_product_attention. This module inherits from
|
| 291 |
+
`DiffLlamaAttention` as the weights of the module stays untouched. The only changes are on the forward pass to adapt to
|
| 292 |
+
SDPA API.
|
| 293 |
+
"""
|
| 294 |
+
|
| 295 |
+
# Adapted from DiffLlamaAttention.forward
|
| 296 |
+
def forward(
|
| 297 |
+
self,
|
| 298 |
+
hidden_states: torch.Tensor,
|
| 299 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 300 |
+
attention_mask: torch.Tensor | None = None,
|
| 301 |
+
position_ids: torch.LongTensor | None = None,
|
| 302 |
+
past_key_values: Cache | None = None,
|
| 303 |
+
use_cache: bool = False,
|
| 304 |
+
**kwargs,
|
| 305 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, tuple[torch.Tensor] | None]:
|
| 306 |
+
bsz, q_len, _ = hidden_states.size()
|
| 307 |
+
|
| 308 |
+
query_states = self.q_proj(hidden_states)
|
| 309 |
+
key_states = self.k_proj(hidden_states)
|
| 310 |
+
value_states = self.v_proj(hidden_states)
|
| 311 |
+
|
| 312 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 313 |
+
key_states = key_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 314 |
+
value_states = value_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 315 |
+
|
| 316 |
+
cos, sin = position_embeddings
|
| 317 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 318 |
+
|
| 319 |
+
if past_key_values is not None:
|
| 320 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 321 |
+
|
| 322 |
+
key_states = repeat_kv(key_states, self.num_key_value_groups)
|
| 323 |
+
value_states = repeat_kv(value_states, self.num_key_value_groups)
|
| 324 |
+
value_states = torch.cat(torch.chunk(value_states, 2, dim=1), dim=-1)
|
| 325 |
+
value_states = value_states.repeat(1, 2, 1, 1)
|
| 326 |
+
|
| 327 |
+
causal_mask = attention_mask
|
| 328 |
+
if attention_mask is not None:
|
| 329 |
+
causal_mask = causal_mask[:, :, :, : key_states.shape[-2]]
|
| 330 |
+
|
| 331 |
+
# We dispatch to SDPA's Flash Attention or Efficient kernels via this `is_causal` if statement instead of an inline conditional assignment
|
| 332 |
+
# in SDPA to support both torch.compile's dynamic shapes and full graph options. An inline conditional prevents dynamic shapes from compiling.
|
| 333 |
+
is_causal = causal_mask is None and q_len > 1
|
| 334 |
+
|
| 335 |
+
attn_output = torch.nn.functional.scaled_dot_product_attention(
|
| 336 |
+
query_states,
|
| 337 |
+
key_states,
|
| 338 |
+
value_states,
|
| 339 |
+
attn_mask=causal_mask,
|
| 340 |
+
dropout_p=self.attention_dropout if self.training else 0.0,
|
| 341 |
+
is_causal=is_causal,
|
| 342 |
+
)
|
| 343 |
+
|
| 344 |
+
attn_output1, attn_output2 = torch.chunk(attn_output, 2, dim=1)
|
| 345 |
+
|
| 346 |
+
lambda_1 = torch.exp(torch.sum(self.lambda_q1 * self.lambda_k1, dim=-1, dtype=torch.float32)).to(
|
| 347 |
+
query_states.dtype
|
| 348 |
+
)
|
| 349 |
+
lambda_2 = torch.exp(torch.sum(self.lambda_q2 * self.lambda_k2, dim=-1, dtype=torch.float32)).to(
|
| 350 |
+
query_states.dtype
|
| 351 |
+
)
|
| 352 |
+
lambda_full = lambda_1 - lambda_2 + self.lambda_init
|
| 353 |
+
|
| 354 |
+
attn_output = attn_output1 - lambda_full * attn_output2
|
| 355 |
+
attn_output = (1 - self.lambda_init) * self.groupnorm(attn_output)
|
| 356 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 357 |
+
attn_output = attn_output.view(bsz, q_len, -1)
|
| 358 |
+
attn_output = self.o_proj(attn_output)
|
| 359 |
+
return attn_output, None
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
DIFFLLAMA_ATTENTION_CLASSES = {
|
| 363 |
+
"eager": DiffLlamaAttention,
|
| 364 |
+
"flash_attention_2": DiffLlamaFlashAttention2,
|
| 365 |
+
"sdpa": DiffLlamaSdpaAttention,
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
|
| 369 |
+
class DiffLlamaDecoderLayer(LlamaDecoderLayer):
|
| 370 |
+
def __init__(self, config: DiffLlamaConfig, layer_idx: int):
|
| 371 |
+
super().__init__(config, layer_idx)
|
| 372 |
+
|
| 373 |
+
self.self_attn = DIFFLLAMA_ATTENTION_CLASSES[config._attn_implementation](config=config, layer_idx=layer_idx)
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
class DiffLlamaPreTrainedModel(LlamaPreTrainedModel):
|
| 377 |
+
_supports_flex_attn = False
|
| 378 |
+
_supports_attention_backend = False
|
| 379 |
+
|
| 380 |
+
@torch.no_grad()
|
| 381 |
+
def _init_weights(self, module):
|
| 382 |
+
PreTrainedModel._init_weights(self, module)
|
| 383 |
+
if isinstance(module, DiffLlamaAttention):
|
| 384 |
+
init.normal_(module.lambda_q1, 0, self.config.lambda_std_dev)
|
| 385 |
+
init.normal_(module.lambda_k1, 0, self.config.lambda_std_dev)
|
| 386 |
+
init.normal_(module.lambda_q2, 0, self.config.lambda_std_dev)
|
| 387 |
+
init.normal_(module.lambda_k2, 0, self.config.lambda_std_dev)
|
| 388 |
+
|
| 389 |
+
|
| 390 |
+
class DiffLlamaModel(LlamaModel):
|
| 391 |
+
pass
|
| 392 |
+
|
| 393 |
+
|
| 394 |
+
class DiffLlamaForCausalLM(GemmaForCausalLM):
|
| 395 |
+
pass
|
| 396 |
+
|
| 397 |
+
|
| 398 |
+
class DiffLlamaForSequenceClassification(LlamaForSequenceClassification):
|
| 399 |
+
pass
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
class DiffLlamaForQuestionAnswering(LlamaForQuestionAnswering):
|
| 403 |
+
pass
|
| 404 |
+
|
| 405 |
+
|
| 406 |
+
class DiffLlamaForTokenClassification(LlamaForTokenClassification):
|
| 407 |
+
pass
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
__all__ = [
|
| 411 |
+
"DiffLlamaPreTrainedModel",
|
| 412 |
+
"DiffLlamaModel",
|
| 413 |
+
"DiffLlamaForCausalLM",
|
| 414 |
+
"DiffLlamaForSequenceClassification",
|
| 415 |
+
"DiffLlamaForQuestionAnswering",
|
| 416 |
+
"DiffLlamaForTokenClassification",
|
| 417 |
+
]
|
third_party/transformers/src/transformers/models/encodec/__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_encodec import *
|
| 22 |
+
from .feature_extraction_encodec import *
|
| 23 |
+
from .modeling_encodec import *
|
| 24 |
+
else:
|
| 25 |
+
import sys
|
| 26 |
+
|
| 27 |
+
_file = globals()["__file__"]
|
| 28 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/encodec/configuration_encodec.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 Meta Platforms, Inc. and affiliates, and the HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""EnCodec model configuration"""
|
| 15 |
+
|
| 16 |
+
import math
|
| 17 |
+
|
| 18 |
+
import numpy as np
|
| 19 |
+
from huggingface_hub.dataclasses import strict
|
| 20 |
+
|
| 21 |
+
from ...configuration_utils import PreTrainedConfig
|
| 22 |
+
from ...utils import auto_docstring
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
@auto_docstring(checkpoint="facebook/encodec_24khz")
|
| 26 |
+
@strict
|
| 27 |
+
class EncodecConfig(PreTrainedConfig):
|
| 28 |
+
r"""
|
| 29 |
+
target_bandwidths (`list[float]`, *optional*, defaults to `[1.5, 3.0, 6.0, 12.0, 24.0]`):
|
| 30 |
+
The range of different bandwidths the model can encode audio with.
|
| 31 |
+
normalize (`bool`, *optional*, defaults to `False`):
|
| 32 |
+
Whether the audio shall be normalized when passed.
|
| 33 |
+
chunk_length_s (`float`, *optional*):
|
| 34 |
+
If defined the audio is pre-processed into chunks of lengths `chunk_length_s` and then encoded.
|
| 35 |
+
overlap (`float`, *optional*):
|
| 36 |
+
Defines the overlap between each chunk. It is used to compute the `chunk_stride` using the following
|
| 37 |
+
formulae : `int((1.0 - self.overlap) * self.chunk_length)`.
|
| 38 |
+
num_filters (`int`, *optional*, defaults to 32):
|
| 39 |
+
Number of convolution kernels of first `EncodecConv1d` down sampling layer.
|
| 40 |
+
num_residual_layers (`int`, *optional*, defaults to 1):
|
| 41 |
+
Number of residual layers.
|
| 42 |
+
upsampling_ratios (`Sequence[int]` , *optional*, defaults to `[8, 5, 4, 2]`):
|
| 43 |
+
Kernel size and stride ratios. The encoder uses downsampling ratios instead of upsampling ratios, hence it
|
| 44 |
+
will use the ratios in the reverse order to the ones specified here that must match the decoder order.
|
| 45 |
+
norm_type (`str`, *optional*, defaults to `"weight_norm"`):
|
| 46 |
+
Normalization method. Should be in `["weight_norm", "time_group_norm"]`
|
| 47 |
+
kernel_size (`int`, *optional*, defaults to 7):
|
| 48 |
+
Kernel size for the initial convolution.
|
| 49 |
+
last_kernel_size (`int`, *optional*, defaults to 7):
|
| 50 |
+
Kernel size for the last convolution layer.
|
| 51 |
+
residual_kernel_size (`int`, *optional*, defaults to 3):
|
| 52 |
+
Kernel size for the residual layers.
|
| 53 |
+
dilation_growth_rate (`int`, *optional*, defaults to 2):
|
| 54 |
+
How much to increase the dilation with each layer.
|
| 55 |
+
use_causal_conv (`bool`, *optional*, defaults to `True`):
|
| 56 |
+
Whether to use fully causal convolution.
|
| 57 |
+
pad_mode (`str`, *optional*, defaults to `"reflect"`):
|
| 58 |
+
Padding mode for the convolutions.
|
| 59 |
+
compress (`int`, *optional*, defaults to 2):
|
| 60 |
+
Reduced dimensionality in residual branches (from Demucs v3).
|
| 61 |
+
num_lstm_layers (`int`, *optional*, defaults to 2):
|
| 62 |
+
Number of LSTM layers at the end of the encoder.
|
| 63 |
+
trim_right_ratio (`float`, *optional*, defaults to 1.0):
|
| 64 |
+
Ratio for trimming at the right of the transposed convolution under the `use_causal_conv = True` setup. If
|
| 65 |
+
equal to 1.0, it means that all the trimming is done at the right.
|
| 66 |
+
use_conv_shortcut (`bool`, *optional*, defaults to `True`):
|
| 67 |
+
Whether to use a convolutional layer as the 'skip' connection in the `EncodecResnetBlock` block. If False,
|
| 68 |
+
an identity function will be used, giving a generic residual connection.
|
| 69 |
+
|
| 70 |
+
Example:
|
| 71 |
+
|
| 72 |
+
```python
|
| 73 |
+
>>> from transformers import EncodecModel, EncodecConfig
|
| 74 |
+
|
| 75 |
+
>>> # Initializing a "facebook/encodec_24khz" style configuration
|
| 76 |
+
>>> configuration = EncodecConfig()
|
| 77 |
+
|
| 78 |
+
>>> # Initializing a model (with random weights) from the "facebook/encodec_24khz" style configuration
|
| 79 |
+
>>> model = EncodecModel(configuration)
|
| 80 |
+
|
| 81 |
+
>>> # Accessing the model configuration
|
| 82 |
+
>>> configuration = model.config
|
| 83 |
+
```"""
|
| 84 |
+
|
| 85 |
+
model_type = "encodec"
|
| 86 |
+
|
| 87 |
+
target_bandwidths: list[float] | tuple[float, ...] = (1.5, 3.0, 6.0, 12.0, 24.0)
|
| 88 |
+
sampling_rate: int = 24_000
|
| 89 |
+
audio_channels: int = 1
|
| 90 |
+
normalize: bool = False
|
| 91 |
+
chunk_length_s: int | float | None = None
|
| 92 |
+
overlap: float | None = None
|
| 93 |
+
hidden_size: int = 128
|
| 94 |
+
num_filters: int = 32
|
| 95 |
+
num_residual_layers: int = 1
|
| 96 |
+
upsampling_ratios: list[int] | tuple[int, ...] = (8, 5, 4, 2)
|
| 97 |
+
norm_type: str = "weight_norm"
|
| 98 |
+
kernel_size: int = 7
|
| 99 |
+
last_kernel_size: int = 7
|
| 100 |
+
residual_kernel_size: int = 3
|
| 101 |
+
dilation_growth_rate: int = 2
|
| 102 |
+
use_causal_conv: bool = True
|
| 103 |
+
pad_mode: str = "reflect"
|
| 104 |
+
compress: int = 2
|
| 105 |
+
num_lstm_layers: int = 2
|
| 106 |
+
trim_right_ratio: float = 1.0
|
| 107 |
+
codebook_size: int = 1024
|
| 108 |
+
codebook_dim: int | None = None
|
| 109 |
+
use_conv_shortcut: bool = True
|
| 110 |
+
|
| 111 |
+
def __post_init__(self, **kwargs):
|
| 112 |
+
self.codebook_dim = self.codebook_dim if self.codebook_dim is not None else self.hidden_size
|
| 113 |
+
super().__post_init__(**kwargs)
|
| 114 |
+
|
| 115 |
+
def validate_architecture(self):
|
| 116 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 117 |
+
if self.norm_type not in ["weight_norm", "time_group_norm"]:
|
| 118 |
+
raise ValueError(
|
| 119 |
+
f'self.norm_type must be one of `"weight_norm"`, `"time_group_norm"`), got {self.norm_type}'
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
# This is a property because you might want to change the chunk_length_s on the fly
|
| 123 |
+
@property
|
| 124 |
+
def chunk_length(self) -> int | None:
|
| 125 |
+
if self.chunk_length_s is None:
|
| 126 |
+
return None
|
| 127 |
+
else:
|
| 128 |
+
return int(self.chunk_length_s * self.sampling_rate)
|
| 129 |
+
|
| 130 |
+
# This is a property because you might want to change the chunk_length_s on the fly
|
| 131 |
+
@property
|
| 132 |
+
def chunk_stride(self) -> int | None:
|
| 133 |
+
if self.chunk_length_s is None or self.overlap is None:
|
| 134 |
+
return None
|
| 135 |
+
else:
|
| 136 |
+
return max(1, int((1.0 - self.overlap) * self.chunk_length))
|
| 137 |
+
|
| 138 |
+
@property
|
| 139 |
+
def hop_length(self) -> int:
|
| 140 |
+
return int(np.prod(self.upsampling_ratios))
|
| 141 |
+
|
| 142 |
+
@property
|
| 143 |
+
def codebook_nbits(self) -> int:
|
| 144 |
+
return math.ceil(math.log2(self.codebook_size))
|
| 145 |
+
|
| 146 |
+
@property
|
| 147 |
+
def frame_rate(self) -> int:
|
| 148 |
+
return math.ceil(self.sampling_rate / self.hop_length)
|
| 149 |
+
|
| 150 |
+
@property
|
| 151 |
+
def num_quantizers(self) -> int:
|
| 152 |
+
return int(1000 * self.target_bandwidths[-1] // (self.frame_rate * self.codebook_nbits))
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
__all__ = ["EncodecConfig"]
|
third_party/transformers/src/transformers/models/encodec/convert_encodec_checkpoint_to_pytorch.py
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert EnCodec checkpoints."""
|
| 15 |
+
|
| 16 |
+
import argparse
|
| 17 |
+
|
| 18 |
+
import torch
|
| 19 |
+
|
| 20 |
+
from transformers import (
|
| 21 |
+
EncodecConfig,
|
| 22 |
+
EncodecFeatureExtractor,
|
| 23 |
+
EncodecModel,
|
| 24 |
+
logging,
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
# checkpoints downloaded from:
|
| 29 |
+
# https://dl.fbaipublicfiles.com/encodec/v0/encodec_24khz-d7cc33bc.th
|
| 30 |
+
# https://huggingface.co/facebook/musicgen-small/resolve/main/compression_state_dict.bin
|
| 31 |
+
# https://dl.fbaipublicfiles.com/encodec/v0/encodec_48khz-7e698e3e.th
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
logging.set_verbosity_info()
|
| 35 |
+
logger = logging.get_logger("transformers.models.encodec")
|
| 36 |
+
|
| 37 |
+
MAPPING_QUANTIZER = {
|
| 38 |
+
"quantizer.vq.layers.*._codebook.inited": "quantizer.layers.*.codebook.inited",
|
| 39 |
+
"quantizer.vq.layers.*._codebook.cluster_size": "quantizer.layers.*.codebook.cluster_size",
|
| 40 |
+
"quantizer.vq.layers.*._codebook.embed": "quantizer.layers.*.codebook.embed",
|
| 41 |
+
"quantizer.vq.layers.*._codebook.embed_avg": "quantizer.layers.*.codebook.embed_avg",
|
| 42 |
+
}
|
| 43 |
+
MAPPING_ENCODER = {
|
| 44 |
+
"encoder.model.0.conv.conv": "encoder.layers.0.conv",
|
| 45 |
+
"encoder.model.1.block.1.conv.conv": "encoder.layers.1.block.1.conv",
|
| 46 |
+
"encoder.model.1.block.3.conv.conv": "encoder.layers.1.block.3.conv",
|
| 47 |
+
"encoder.model.1.shortcut.conv.conv": "encoder.layers.1.shortcut.conv",
|
| 48 |
+
"encoder.model.3.conv.conv": "encoder.layers.3.conv",
|
| 49 |
+
"encoder.model.4.block.1.conv.conv": "encoder.layers.4.block.1.conv",
|
| 50 |
+
"encoder.model.4.block.3.conv.conv": "encoder.layers.4.block.3.conv",
|
| 51 |
+
"encoder.model.4.shortcut.conv.conv": "encoder.layers.4.shortcut.conv",
|
| 52 |
+
"encoder.model.6.conv.conv": "encoder.layers.6.conv",
|
| 53 |
+
"encoder.model.7.block.1.conv.conv": "encoder.layers.7.block.1.conv",
|
| 54 |
+
"encoder.model.7.block.3.conv.conv": "encoder.layers.7.block.3.conv",
|
| 55 |
+
"encoder.model.7.shortcut.conv.conv": "encoder.layers.7.shortcut.conv",
|
| 56 |
+
"encoder.model.9.conv.conv": "encoder.layers.9.conv",
|
| 57 |
+
"encoder.model.10.block.1.conv.conv": "encoder.layers.10.block.1.conv",
|
| 58 |
+
"encoder.model.10.block.3.conv.conv": "encoder.layers.10.block.3.conv",
|
| 59 |
+
"encoder.model.10.shortcut.conv.conv": "encoder.layers.10.shortcut.conv",
|
| 60 |
+
"encoder.model.12.conv.conv": "encoder.layers.12.conv",
|
| 61 |
+
"encoder.model.13.lstm": "encoder.layers.13.lstm",
|
| 62 |
+
"encoder.model.15.conv.conv": "encoder.layers.15.conv",
|
| 63 |
+
}
|
| 64 |
+
MAPPING_ENCODER_48K = {
|
| 65 |
+
"encoder.model.0.conv.norm": "encoder.layers.0.norm",
|
| 66 |
+
"encoder.model.1.block.1.conv.norm": "encoder.layers.1.block.1.norm",
|
| 67 |
+
"encoder.model.1.block.3.conv.norm": "encoder.layers.1.block.3.norm",
|
| 68 |
+
"encoder.model.1.shortcut.conv.norm": "encoder.layers.1.shortcut.norm",
|
| 69 |
+
"encoder.model.3.conv.norm": "encoder.layers.3.norm",
|
| 70 |
+
"encoder.model.4.block.1.conv.norm": "encoder.layers.4.block.1.norm",
|
| 71 |
+
"encoder.model.4.block.3.conv.norm": "encoder.layers.4.block.3.norm",
|
| 72 |
+
"encoder.model.4.shortcut.conv.norm": "encoder.layers.4.shortcut.norm",
|
| 73 |
+
"encoder.model.6.conv.norm": "encoder.layers.6.norm",
|
| 74 |
+
"encoder.model.7.block.1.conv.norm": "encoder.layers.7.block.1.norm",
|
| 75 |
+
"encoder.model.7.block.3.conv.norm": "encoder.layers.7.block.3.norm",
|
| 76 |
+
"encoder.model.7.shortcut.conv.norm": "encoder.layers.7.shortcut.norm",
|
| 77 |
+
"encoder.model.9.conv.norm": "encoder.layers.9.norm",
|
| 78 |
+
"encoder.model.10.block.1.conv.norm": "encoder.layers.10.block.1.norm",
|
| 79 |
+
"encoder.model.10.block.3.conv.norm": "encoder.layers.10.block.3.norm",
|
| 80 |
+
"encoder.model.10.shortcut.conv.norm": "encoder.layers.10.shortcut.norm",
|
| 81 |
+
"encoder.model.12.conv.norm": "encoder.layers.12.norm",
|
| 82 |
+
"encoder.model.15.conv.norm": "encoder.layers.15.norm",
|
| 83 |
+
}
|
| 84 |
+
MAPPING_DECODER = {
|
| 85 |
+
"decoder.model.0.conv.conv": "decoder.layers.0.conv",
|
| 86 |
+
"decoder.model.1.lstm": "decoder.layers.1.lstm",
|
| 87 |
+
"decoder.model.3.convtr.convtr": "decoder.layers.3.conv",
|
| 88 |
+
"decoder.model.4.block.1.conv.conv": "decoder.layers.4.block.1.conv",
|
| 89 |
+
"decoder.model.4.block.3.conv.conv": "decoder.layers.4.block.3.conv",
|
| 90 |
+
"decoder.model.4.shortcut.conv.conv": "decoder.layers.4.shortcut.conv",
|
| 91 |
+
"decoder.model.6.convtr.convtr": "decoder.layers.6.conv",
|
| 92 |
+
"decoder.model.7.block.1.conv.conv": "decoder.layers.7.block.1.conv",
|
| 93 |
+
"decoder.model.7.block.3.conv.conv": "decoder.layers.7.block.3.conv",
|
| 94 |
+
"decoder.model.7.shortcut.conv.conv": "decoder.layers.7.shortcut.conv",
|
| 95 |
+
"decoder.model.9.convtr.convtr": "decoder.layers.9.conv",
|
| 96 |
+
"decoder.model.10.block.1.conv.conv": "decoder.layers.10.block.1.conv",
|
| 97 |
+
"decoder.model.10.block.3.conv.conv": "decoder.layers.10.block.3.conv",
|
| 98 |
+
"decoder.model.10.shortcut.conv.conv": "decoder.layers.10.shortcut.conv",
|
| 99 |
+
"decoder.model.12.convtr.convtr": "decoder.layers.12.conv",
|
| 100 |
+
"decoder.model.13.block.1.conv.conv": "decoder.layers.13.block.1.conv",
|
| 101 |
+
"decoder.model.13.block.3.conv.conv": "decoder.layers.13.block.3.conv",
|
| 102 |
+
"decoder.model.13.shortcut.conv.conv": "decoder.layers.13.shortcut.conv",
|
| 103 |
+
"decoder.model.15.conv.conv": "decoder.layers.15.conv",
|
| 104 |
+
}
|
| 105 |
+
MAPPING_DECODER_48K = {
|
| 106 |
+
"decoder.model.0.conv.norm": "decoder.layers.0.norm",
|
| 107 |
+
"decoder.model.3.convtr.norm": "decoder.layers.3.norm",
|
| 108 |
+
"decoder.model.4.block.1.conv.norm": "decoder.layers.4.block.1.norm",
|
| 109 |
+
"decoder.model.4.block.3.conv.norm": "decoder.layers.4.block.3.norm",
|
| 110 |
+
"decoder.model.4.shortcut.conv.norm": "decoder.layers.4.shortcut.norm",
|
| 111 |
+
"decoder.model.6.convtr.norm": "decoder.layers.6.norm",
|
| 112 |
+
"decoder.model.7.block.1.conv.norm": "decoder.layers.7.block.1.norm",
|
| 113 |
+
"decoder.model.7.block.3.conv.norm": "decoder.layers.7.block.3.norm",
|
| 114 |
+
"decoder.model.7.shortcut.conv.norm": "decoder.layers.7.shortcut.norm",
|
| 115 |
+
"decoder.model.9.convtr.norm": "decoder.layers.9.norm",
|
| 116 |
+
"decoder.model.10.block.1.conv.norm": "decoder.layers.10.block.1.norm",
|
| 117 |
+
"decoder.model.10.block.3.conv.norm": "decoder.layers.10.block.3.norm",
|
| 118 |
+
"decoder.model.10.shortcut.conv.norm": "decoder.layers.10.shortcut.norm",
|
| 119 |
+
"decoder.model.12.convtr.norm": "decoder.layers.12.norm",
|
| 120 |
+
"decoder.model.13.block.1.conv.norm": "decoder.layers.13.block.1.norm",
|
| 121 |
+
"decoder.model.13.block.3.conv.norm": "decoder.layers.13.block.3.norm",
|
| 122 |
+
"decoder.model.13.shortcut.conv.norm": "decoder.layers.13.shortcut.norm",
|
| 123 |
+
"decoder.model.15.conv.norm": "decoder.layers.15.norm",
|
| 124 |
+
}
|
| 125 |
+
MAPPING_24K = {
|
| 126 |
+
**MAPPING_QUANTIZER,
|
| 127 |
+
**MAPPING_ENCODER,
|
| 128 |
+
**MAPPING_DECODER,
|
| 129 |
+
}
|
| 130 |
+
MAPPING_48K = {
|
| 131 |
+
**MAPPING_QUANTIZER,
|
| 132 |
+
**MAPPING_ENCODER,
|
| 133 |
+
**MAPPING_ENCODER_48K,
|
| 134 |
+
**MAPPING_DECODER,
|
| 135 |
+
**MAPPING_DECODER_48K,
|
| 136 |
+
}
|
| 137 |
+
TOP_LEVEL_KEYS = []
|
| 138 |
+
IGNORE_KEYS = []
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def set_recursively(hf_pointer, key, value, full_name, weight_type):
|
| 142 |
+
for attribute in key.split("."):
|
| 143 |
+
hf_pointer = getattr(hf_pointer, attribute)
|
| 144 |
+
|
| 145 |
+
if weight_type is not None:
|
| 146 |
+
hf_shape = getattr(hf_pointer, weight_type).shape
|
| 147 |
+
else:
|
| 148 |
+
hf_shape = hf_pointer.shape
|
| 149 |
+
|
| 150 |
+
if hf_shape != value.shape:
|
| 151 |
+
raise ValueError(
|
| 152 |
+
f"Shape of hf {key + '.' + weight_type if weight_type is not None else ''} is {hf_shape}, but should be"
|
| 153 |
+
f" {value.shape} for {full_name}"
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
if weight_type == "weight":
|
| 157 |
+
hf_pointer.weight.data = value
|
| 158 |
+
elif weight_type == "weight_g":
|
| 159 |
+
hf_pointer.weight_g.data = value
|
| 160 |
+
elif weight_type == "weight_v":
|
| 161 |
+
hf_pointer.weight_v.data = value
|
| 162 |
+
elif weight_type == "bias":
|
| 163 |
+
hf_pointer.bias.data = value
|
| 164 |
+
elif weight_type == "running_mean":
|
| 165 |
+
hf_pointer.running_mean.data = value
|
| 166 |
+
elif weight_type == "running_var":
|
| 167 |
+
hf_pointer.running_var.data = value
|
| 168 |
+
elif weight_type == "num_batches_tracked":
|
| 169 |
+
hf_pointer.num_batches_tracked.data = value
|
| 170 |
+
elif weight_type == "weight_ih_l0":
|
| 171 |
+
hf_pointer.weight_ih_l0.data = value
|
| 172 |
+
elif weight_type == "weight_hh_l0":
|
| 173 |
+
hf_pointer.weight_hh_l0.data = value
|
| 174 |
+
elif weight_type == "bias_ih_l0":
|
| 175 |
+
hf_pointer.bias_ih_l0.data = value
|
| 176 |
+
elif weight_type == "bias_hh_l0":
|
| 177 |
+
hf_pointer.bias_hh_l0.data = value
|
| 178 |
+
elif weight_type == "weight_ih_l1":
|
| 179 |
+
hf_pointer.weight_ih_l1.data = value
|
| 180 |
+
elif weight_type == "weight_hh_l1":
|
| 181 |
+
hf_pointer.weight_hh_l1.data = value
|
| 182 |
+
elif weight_type == "bias_ih_l1":
|
| 183 |
+
hf_pointer.bias_ih_l1.data = value
|
| 184 |
+
elif weight_type == "bias_hh_l1":
|
| 185 |
+
hf_pointer.bias_hh_l1.data = value
|
| 186 |
+
else:
|
| 187 |
+
hf_pointer.data = value
|
| 188 |
+
|
| 189 |
+
logger.info(f"{key + ('.' + weight_type if weight_type is not None else '')} was initialized from {full_name}.")
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
def should_ignore(name, ignore_keys):
|
| 193 |
+
for key in ignore_keys:
|
| 194 |
+
if key.endswith(".*"):
|
| 195 |
+
if name.startswith(key[:-1]):
|
| 196 |
+
return True
|
| 197 |
+
elif ".*." in key:
|
| 198 |
+
prefix, suffix = key.split(".*.")
|
| 199 |
+
if prefix in name and suffix in name:
|
| 200 |
+
return True
|
| 201 |
+
elif key in name:
|
| 202 |
+
return True
|
| 203 |
+
return False
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
def recursively_load_weights(orig_dict, hf_model, model_name):
|
| 207 |
+
unused_weights = []
|
| 208 |
+
|
| 209 |
+
if model_name in ["encodec_24khz", "encodec_32khz"]:
|
| 210 |
+
MAPPING = MAPPING_24K
|
| 211 |
+
elif model_name == "encodec_48khz":
|
| 212 |
+
MAPPING = MAPPING_48K
|
| 213 |
+
else:
|
| 214 |
+
raise ValueError(f"Unsupported model: {model_name}")
|
| 215 |
+
|
| 216 |
+
for name, value in orig_dict.items():
|
| 217 |
+
if should_ignore(name, IGNORE_KEYS):
|
| 218 |
+
logger.info(f"{name} was ignored")
|
| 219 |
+
continue
|
| 220 |
+
|
| 221 |
+
is_used = False
|
| 222 |
+
for key, mapped_key in MAPPING.items():
|
| 223 |
+
if "*" in key:
|
| 224 |
+
prefix, suffix = key.split(".*.")
|
| 225 |
+
if prefix in name and suffix in name:
|
| 226 |
+
key = suffix
|
| 227 |
+
|
| 228 |
+
if key in name:
|
| 229 |
+
# HACK otherwise .embed gets initialized with .embed_avg too
|
| 230 |
+
if key.endswith("embed") and name.endswith("embed_avg"):
|
| 231 |
+
continue
|
| 232 |
+
|
| 233 |
+
is_used = True
|
| 234 |
+
if "*" in mapped_key:
|
| 235 |
+
layer_index = name.split(key)[0].split(".")[-2]
|
| 236 |
+
mapped_key = mapped_key.replace("*", layer_index)
|
| 237 |
+
if "weight_g" in name:
|
| 238 |
+
weight_type = "weight_g"
|
| 239 |
+
elif "weight_v" in name:
|
| 240 |
+
weight_type = "weight_v"
|
| 241 |
+
elif "weight_ih_l0" in name:
|
| 242 |
+
weight_type = "weight_ih_l0"
|
| 243 |
+
elif "weight_hh_l0" in name:
|
| 244 |
+
weight_type = "weight_hh_l0"
|
| 245 |
+
elif "bias_ih_l0" in name:
|
| 246 |
+
weight_type = "bias_ih_l0"
|
| 247 |
+
elif "bias_hh_l0" in name:
|
| 248 |
+
weight_type = "bias_hh_l0"
|
| 249 |
+
elif "weight_ih_l1" in name:
|
| 250 |
+
weight_type = "weight_ih_l1"
|
| 251 |
+
elif "weight_hh_l1" in name:
|
| 252 |
+
weight_type = "weight_hh_l1"
|
| 253 |
+
elif "bias_ih_l1" in name:
|
| 254 |
+
weight_type = "bias_ih_l1"
|
| 255 |
+
elif "bias_hh_l1" in name:
|
| 256 |
+
weight_type = "bias_hh_l1"
|
| 257 |
+
elif "bias" in name:
|
| 258 |
+
weight_type = "bias"
|
| 259 |
+
elif "weight" in name:
|
| 260 |
+
weight_type = "weight"
|
| 261 |
+
elif "running_mean" in name:
|
| 262 |
+
weight_type = "running_mean"
|
| 263 |
+
elif "running_var" in name:
|
| 264 |
+
weight_type = "running_var"
|
| 265 |
+
elif "num_batches_tracked" in name:
|
| 266 |
+
weight_type = "num_batches_tracked"
|
| 267 |
+
else:
|
| 268 |
+
weight_type = None
|
| 269 |
+
set_recursively(hf_model, mapped_key, value, name, weight_type)
|
| 270 |
+
continue
|
| 271 |
+
if not is_used:
|
| 272 |
+
unused_weights.append(name)
|
| 273 |
+
|
| 274 |
+
logger.warning(f"Unused weights: {unused_weights}")
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
@torch.no_grad()
|
| 278 |
+
def convert_checkpoint(
|
| 279 |
+
model_name,
|
| 280 |
+
checkpoint_path,
|
| 281 |
+
pytorch_dump_folder_path,
|
| 282 |
+
config_path=None,
|
| 283 |
+
repo_id=None,
|
| 284 |
+
):
|
| 285 |
+
"""
|
| 286 |
+
Copy/paste/tweak model's weights to transformers design.
|
| 287 |
+
"""
|
| 288 |
+
if config_path is not None:
|
| 289 |
+
config = EncodecConfig.from_pretrained(config_path)
|
| 290 |
+
else:
|
| 291 |
+
config = EncodecConfig()
|
| 292 |
+
|
| 293 |
+
if model_name == "encodec_24khz":
|
| 294 |
+
pass # config is already correct
|
| 295 |
+
elif model_name == "encodec_32khz":
|
| 296 |
+
config.upsampling_ratios = [8, 5, 4, 4]
|
| 297 |
+
config.target_bandwidths = [2.2]
|
| 298 |
+
config.num_filters = 64
|
| 299 |
+
config.sampling_rate = 32_000
|
| 300 |
+
config.codebook_size = 2048
|
| 301 |
+
config.use_causal_conv = False
|
| 302 |
+
config.normalize = False
|
| 303 |
+
config.use_conv_shortcut = False
|
| 304 |
+
elif model_name == "encodec_48khz":
|
| 305 |
+
config.upsampling_ratios = [8, 5, 4, 2]
|
| 306 |
+
config.target_bandwidths = [3.0, 6.0, 12.0, 24.0]
|
| 307 |
+
config.sampling_rate = 48_000
|
| 308 |
+
config.audio_channels = 2
|
| 309 |
+
config.use_causal_conv = False
|
| 310 |
+
config.norm_type = "time_group_norm"
|
| 311 |
+
config.normalize = True
|
| 312 |
+
config.chunk_length_s = 1.0
|
| 313 |
+
config.overlap = 0.01
|
| 314 |
+
else:
|
| 315 |
+
raise ValueError(f"Unknown model name: {model_name}")
|
| 316 |
+
|
| 317 |
+
model = EncodecModel(config)
|
| 318 |
+
|
| 319 |
+
feature_extractor = EncodecFeatureExtractor(
|
| 320 |
+
feature_size=config.audio_channels,
|
| 321 |
+
sampling_rate=config.sampling_rate,
|
| 322 |
+
chunk_length_s=config.chunk_length_s,
|
| 323 |
+
overlap=config.overlap,
|
| 324 |
+
)
|
| 325 |
+
feature_extractor.save_pretrained(pytorch_dump_folder_path)
|
| 326 |
+
|
| 327 |
+
original_checkpoint = torch.load(checkpoint_path, weights_only=True)
|
| 328 |
+
if "best_state" in original_checkpoint:
|
| 329 |
+
# we might have a training state saved, in which case discard the yaml results and just retain the weights
|
| 330 |
+
original_checkpoint = original_checkpoint["best_state"]
|
| 331 |
+
recursively_load_weights(original_checkpoint, model, model_name)
|
| 332 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 333 |
+
|
| 334 |
+
if repo_id:
|
| 335 |
+
print("Pushing to the hub...")
|
| 336 |
+
feature_extractor.push_to_hub(repo_id)
|
| 337 |
+
model.push_to_hub(repo_id)
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
if __name__ == "__main__":
|
| 341 |
+
parser = argparse.ArgumentParser()
|
| 342 |
+
parser.add_argument(
|
| 343 |
+
"--model",
|
| 344 |
+
default="encodec_24khz",
|
| 345 |
+
type=str,
|
| 346 |
+
help="The model to convert. Should be one of 'encodec_24khz', 'encodec_32khz', 'encodec_48khz'.",
|
| 347 |
+
)
|
| 348 |
+
parser.add_argument("--checkpoint_path", required=True, default=None, type=str, help="Path to original checkpoint")
|
| 349 |
+
parser.add_argument("--config_path", default=None, type=str, help="Path to hf config.json of model to convert")
|
| 350 |
+
parser.add_argument(
|
| 351 |
+
"--pytorch_dump_folder_path", required=True, default=None, type=str, help="Path to the output PyTorch model."
|
| 352 |
+
)
|
| 353 |
+
parser.add_argument(
|
| 354 |
+
"--push_to_hub", default=None, type=str, help="Where to upload the converted model on the Hugging Face hub."
|
| 355 |
+
)
|
| 356 |
+
|
| 357 |
+
args = parser.parse_args()
|
| 358 |
+
convert_checkpoint(
|
| 359 |
+
args.model,
|
| 360 |
+
args.checkpoint_path,
|
| 361 |
+
args.pytorch_dump_folder_path,
|
| 362 |
+
args.config_path,
|
| 363 |
+
args.push_to_hub,
|
| 364 |
+
)
|
third_party/transformers/src/transformers/models/encodec/feature_extraction_encodec.py
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Feature extractor class for EnCodec."""
|
| 15 |
+
|
| 16 |
+
import numpy as np
|
| 17 |
+
|
| 18 |
+
from ...feature_extraction_sequence_utils import SequenceFeatureExtractor
|
| 19 |
+
from ...feature_extraction_utils import BatchFeature
|
| 20 |
+
from ...utils import PaddingStrategy, TensorType, logging
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
logger = logging.get_logger(__name__)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class EncodecFeatureExtractor(SequenceFeatureExtractor):
|
| 27 |
+
r"""
|
| 28 |
+
Constructs an EnCodec feature extractor.
|
| 29 |
+
|
| 30 |
+
This feature extractor inherits from [`~feature_extraction_sequence_utils.SequenceFeatureExtractor`] which contains
|
| 31 |
+
most of the main methods. Users should refer to this superclass for more information regarding those methods.
|
| 32 |
+
|
| 33 |
+
Instantiating a feature extractor with the defaults will yield a similar configuration to that of the
|
| 34 |
+
[facebook/encodec_24khz](https://huggingface.co/facebook/encodec_24khz) architecture.
|
| 35 |
+
|
| 36 |
+
Args:
|
| 37 |
+
feature_size (`int`, *optional*, defaults to 1):
|
| 38 |
+
The feature dimension of the extracted features. Use 1 for mono, 2 for stereo.
|
| 39 |
+
sampling_rate (`int`, *optional*, defaults to 24000):
|
| 40 |
+
The sampling rate at which the audio waveform should be digitalized expressed in hertz (Hz).
|
| 41 |
+
padding_value (`float`, *optional*, defaults to 0.0):
|
| 42 |
+
The value that is used to fill the padding values.
|
| 43 |
+
chunk_length_s (`float`, *optional*):
|
| 44 |
+
If defined the audio is pre-processed into chunks of lengths `chunk_length_s` and then encoded.
|
| 45 |
+
overlap (`float`, *optional*):
|
| 46 |
+
Defines the overlap between each chunk. It is used to compute the `chunk_stride` using the following
|
| 47 |
+
formulae : `int((1.0 - self.overlap) * self.chunk_length)`.
|
| 48 |
+
"""
|
| 49 |
+
|
| 50 |
+
model_input_names = ["input_values", "padding_mask"]
|
| 51 |
+
|
| 52 |
+
def __init__(
|
| 53 |
+
self,
|
| 54 |
+
feature_size: int = 1,
|
| 55 |
+
sampling_rate: int = 24000,
|
| 56 |
+
padding_value: float = 0.0,
|
| 57 |
+
chunk_length_s: float | None = None,
|
| 58 |
+
overlap: float | None = None,
|
| 59 |
+
**kwargs,
|
| 60 |
+
):
|
| 61 |
+
super().__init__(feature_size=feature_size, sampling_rate=sampling_rate, padding_value=padding_value, **kwargs)
|
| 62 |
+
self.chunk_length_s = chunk_length_s
|
| 63 |
+
self.overlap = overlap
|
| 64 |
+
|
| 65 |
+
# This is a property because you might want to change the chunk_length_s on the fly
|
| 66 |
+
@property
|
| 67 |
+
def chunk_length(self) -> int | None:
|
| 68 |
+
if self.chunk_length_s is None:
|
| 69 |
+
return None
|
| 70 |
+
else:
|
| 71 |
+
return int(self.chunk_length_s * self.sampling_rate)
|
| 72 |
+
|
| 73 |
+
# This is a property because you might want to change the chunk_length_s on the fly
|
| 74 |
+
@property
|
| 75 |
+
def chunk_stride(self) -> int | None:
|
| 76 |
+
if self.chunk_length_s is None or self.overlap is None:
|
| 77 |
+
return None
|
| 78 |
+
else:
|
| 79 |
+
return max(1, int((1.0 - self.overlap) * self.chunk_length))
|
| 80 |
+
|
| 81 |
+
def __call__(
|
| 82 |
+
self,
|
| 83 |
+
raw_audio: np.ndarray | list[float] | list[np.ndarray] | list[list[float]],
|
| 84 |
+
padding: bool | str | PaddingStrategy | None = None,
|
| 85 |
+
truncation: bool | None = False,
|
| 86 |
+
max_length: int | None = None,
|
| 87 |
+
return_tensors: str | TensorType | None = None,
|
| 88 |
+
sampling_rate: int | None = None,
|
| 89 |
+
) -> BatchFeature:
|
| 90 |
+
"""
|
| 91 |
+
Main method to featurize and prepare for the model one or several sequence(s).
|
| 92 |
+
|
| 93 |
+
Args:
|
| 94 |
+
raw_audio (`np.ndarray`, `list[float]`, `list[np.ndarray]`, `list[list[float]]`):
|
| 95 |
+
The sequence or batch of sequences to be processed. Each sequence can be a numpy array, a list of float
|
| 96 |
+
values, a list of numpy arrays or a list of list of float values. The numpy array must be of shape
|
| 97 |
+
`(num_samples,)` for mono audio (`feature_size = 1`), or `(2, num_samples)` for stereo audio
|
| 98 |
+
(`feature_size = 2`).
|
| 99 |
+
padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `True`):
|
| 100 |
+
Select a strategy to pad the returned sequences (according to the model's padding side and padding
|
| 101 |
+
index) among:
|
| 102 |
+
|
| 103 |
+
- `True` or `'longest'`: Pad to the longest sequence in the batch (or no padding if only a single
|
| 104 |
+
sequence if provided).
|
| 105 |
+
- `'max_length'`: Pad to a maximum length specified with the argument `max_length` or to the maximum
|
| 106 |
+
acceptable input length for the model if that argument is not provided.
|
| 107 |
+
- `False` or `'do_not_pad'` (default): No padding (i.e., can output a batch with sequences of different
|
| 108 |
+
lengths).
|
| 109 |
+
truncation (`bool`, *optional*, defaults to `False`):
|
| 110 |
+
Activates truncation to cut input sequences longer than `max_length` to `max_length`.
|
| 111 |
+
max_length (`int`, *optional*):
|
| 112 |
+
Maximum length of the returned list and optionally padding length (see above).
|
| 113 |
+
return_tensors (`str` or [`~utils.TensorType`], *optional*):
|
| 114 |
+
If set, will return tensors instead of list of python integers. Acceptable values are:
|
| 115 |
+
|
| 116 |
+
- `'pt'`: Return PyTorch `torch.Tensor` objects.
|
| 117 |
+
- `'np'`: Return Numpy `np.ndarray` objects.
|
| 118 |
+
sampling_rate (`int`, *optional*):
|
| 119 |
+
The sampling rate at which the `audio` input was sampled. It is strongly recommended to pass
|
| 120 |
+
`sampling_rate` at the forward call to prevent silent errors.
|
| 121 |
+
"""
|
| 122 |
+
if sampling_rate is not None:
|
| 123 |
+
if sampling_rate != self.sampling_rate:
|
| 124 |
+
raise ValueError(
|
| 125 |
+
f"The model corresponding to this feature extractor: {self} was trained using a sampling rate of"
|
| 126 |
+
f" {self.sampling_rate}. Please make sure that the provided audio input was sampled with"
|
| 127 |
+
f" {self.sampling_rate} and not {sampling_rate}."
|
| 128 |
+
)
|
| 129 |
+
else:
|
| 130 |
+
logger.warning(
|
| 131 |
+
f"It is strongly recommended to pass the `sampling_rate` argument to `{self.__class__.__name__}()`. "
|
| 132 |
+
"Failing to do so can result in silent errors that might be hard to debug."
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
if padding and truncation:
|
| 136 |
+
raise ValueError("Both padding and truncation were set. Make sure you only set one.")
|
| 137 |
+
elif padding is None:
|
| 138 |
+
# by default let's pad the inputs
|
| 139 |
+
padding = True
|
| 140 |
+
|
| 141 |
+
is_batched = bool(
|
| 142 |
+
isinstance(raw_audio, (list, tuple)) and (isinstance(raw_audio[0], (np.ndarray, tuple, list)))
|
| 143 |
+
)
|
| 144 |
+
|
| 145 |
+
if is_batched:
|
| 146 |
+
raw_audio = [np.asarray(audio, dtype=np.float32).T for audio in raw_audio]
|
| 147 |
+
elif not is_batched and not isinstance(raw_audio, np.ndarray):
|
| 148 |
+
raw_audio = np.asarray(raw_audio, dtype=np.float32)
|
| 149 |
+
elif isinstance(raw_audio, np.ndarray) and raw_audio.dtype is np.dtype(np.float64):
|
| 150 |
+
raw_audio = raw_audio.astype(np.float32)
|
| 151 |
+
|
| 152 |
+
# always return batch
|
| 153 |
+
if not is_batched:
|
| 154 |
+
raw_audio = [np.asarray(raw_audio).T]
|
| 155 |
+
|
| 156 |
+
# verify inputs are valid
|
| 157 |
+
for idx, example in enumerate(raw_audio):
|
| 158 |
+
if example.ndim > 2:
|
| 159 |
+
raise ValueError(f"Expected input shape (channels, length) but got shape {example.shape}")
|
| 160 |
+
if self.feature_size == 1 and example.ndim != 1:
|
| 161 |
+
raise ValueError(f"Expected mono audio but example has {example.shape[-1]} channels")
|
| 162 |
+
if self.feature_size == 2 and example.shape[-1] != 2:
|
| 163 |
+
raise ValueError(f"Expected stereo audio but example has {example.shape[-1]} channels")
|
| 164 |
+
|
| 165 |
+
padded_inputs = None
|
| 166 |
+
input_values = BatchFeature({"input_values": raw_audio})
|
| 167 |
+
if self.chunk_stride is not None and self.chunk_length is not None and max_length is None:
|
| 168 |
+
if truncation:
|
| 169 |
+
max_length = min(array.shape[0] for array in raw_audio)
|
| 170 |
+
nb_step = int(np.floor(max_length / self.chunk_stride))
|
| 171 |
+
max_length = (nb_step - 1) * self.chunk_stride + self.chunk_length
|
| 172 |
+
elif padding:
|
| 173 |
+
max_length = max(array.shape[0] for array in raw_audio)
|
| 174 |
+
nb_step = int(np.ceil(max_length / self.chunk_stride))
|
| 175 |
+
max_length = (nb_step - 1) * self.chunk_stride + self.chunk_length
|
| 176 |
+
padding = "max_length"
|
| 177 |
+
else:
|
| 178 |
+
padded_inputs = input_values
|
| 179 |
+
|
| 180 |
+
# normal padding on batch
|
| 181 |
+
if padded_inputs is None:
|
| 182 |
+
padded_inputs = self.pad(
|
| 183 |
+
input_values,
|
| 184 |
+
max_length=max_length,
|
| 185 |
+
truncation=truncation,
|
| 186 |
+
padding=padding,
|
| 187 |
+
return_attention_mask=padding,
|
| 188 |
+
)
|
| 189 |
+
if padding:
|
| 190 |
+
padded_inputs["padding_mask"] = padded_inputs.pop("attention_mask")
|
| 191 |
+
|
| 192 |
+
input_values = []
|
| 193 |
+
for example in padded_inputs.pop("input_values"):
|
| 194 |
+
if self.feature_size == 1:
|
| 195 |
+
example = example[..., None]
|
| 196 |
+
input_values.append(example.T)
|
| 197 |
+
|
| 198 |
+
padded_inputs["input_values"] = input_values
|
| 199 |
+
if return_tensors is not None:
|
| 200 |
+
padded_inputs = padded_inputs.convert_to_tensors(return_tensors)
|
| 201 |
+
|
| 202 |
+
return padded_inputs
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
__all__ = ["EncodecFeatureExtractor"]
|
third_party/transformers/src/transformers/models/encodec/modeling_encodec.py
ADDED
|
@@ -0,0 +1,822 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 Meta Platforms, Inc. and affiliates, and the HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch EnCodec model."""
|
| 15 |
+
|
| 16 |
+
import math
|
| 17 |
+
from dataclasses import dataclass
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
from torch import nn
|
| 21 |
+
|
| 22 |
+
from ... import initialization as init
|
| 23 |
+
from ...modeling_utils import PreTrainedAudioTokenizerBase
|
| 24 |
+
from ...utils import (
|
| 25 |
+
ModelOutput,
|
| 26 |
+
auto_docstring,
|
| 27 |
+
logging,
|
| 28 |
+
)
|
| 29 |
+
from .configuration_encodec import EncodecConfig
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
logger = logging.get_logger(__name__)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
# General docstring
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
@dataclass
|
| 39 |
+
@auto_docstring
|
| 40 |
+
class EncodecOutput(ModelOutput):
|
| 41 |
+
r"""
|
| 42 |
+
audio_codes (`torch.LongTensor` of shape `(nb_frames, batch_size, nb_quantizers, frame_len)`, *optional*):
|
| 43 |
+
Discrete code embeddings computed using `model.encode`.
|
| 44 |
+
audio_values (`torch.FloatTensor` of shape `(batch_size, segment_length)`, *optional*):
|
| 45 |
+
Decoded audio values, obtained using the decoder part of Encodec.
|
| 46 |
+
"""
|
| 47 |
+
|
| 48 |
+
audio_codes: torch.LongTensor | None = None
|
| 49 |
+
audio_values: torch.FloatTensor | None = None
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
@dataclass
|
| 53 |
+
@auto_docstring
|
| 54 |
+
class EncodecEncoderOutput(ModelOutput):
|
| 55 |
+
r"""
|
| 56 |
+
audio_codes (`torch.LongTensor` of shape `(nb_frames, batch_size, nb_quantizers, frame_len)`, *optional*):
|
| 57 |
+
Discrete code embeddings computed using `model.encode`.
|
| 58 |
+
audio_scales (list of length `nb_frames` of `torch.Tensor` of shape `(batch_size, 1)`, *optional*):
|
| 59 |
+
Scaling factor for each `audio_codes` input. This is used to unscale each chunk of audio when decoding.
|
| 60 |
+
last_frame_pad_length (`int`, *optional*):
|
| 61 |
+
The length of the padding in the last frame, if any. This is used to ensure that the encoded frames can be
|
| 62 |
+
outputted as a tensor. This value should be passed during decoding to ensure padding is removed from the
|
| 63 |
+
encoded frames.
|
| 64 |
+
"""
|
| 65 |
+
|
| 66 |
+
audio_codes: torch.LongTensor | None = None
|
| 67 |
+
audio_scales: torch.FloatTensor | None = None
|
| 68 |
+
last_frame_pad_length: int | None = None
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
@dataclass
|
| 72 |
+
@auto_docstring
|
| 73 |
+
class EncodecDecoderOutput(ModelOutput):
|
| 74 |
+
r"""
|
| 75 |
+
audio_values (`torch.FloatTensor` of shape `(batch_size, segment_length)`, *optional*):
|
| 76 |
+
Decoded audio values, obtained using the decoder part of Encodec.
|
| 77 |
+
"""
|
| 78 |
+
|
| 79 |
+
audio_values: torch.FloatTensor | None = None
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
class EncodecConv1d(nn.Module):
|
| 83 |
+
"""Conv1d with asymmetric or causal padding and normalization."""
|
| 84 |
+
|
| 85 |
+
def __init__(
|
| 86 |
+
self, config, in_channels: int, out_channels: int, kernel_size: int, stride: int = 1, dilation: int = 1
|
| 87 |
+
):
|
| 88 |
+
super().__init__()
|
| 89 |
+
self.causal = config.use_causal_conv
|
| 90 |
+
self.pad_mode = config.pad_mode
|
| 91 |
+
self.norm_type = config.norm_type
|
| 92 |
+
|
| 93 |
+
if self.norm_type not in ["weight_norm", "time_group_norm"]:
|
| 94 |
+
raise ValueError(
|
| 95 |
+
f'self.norm_type must be one of `"weight_norm"`, `"time_group_norm"`), got {self.norm_type}'
|
| 96 |
+
)
|
| 97 |
+
|
| 98 |
+
# warn user on unusual setup between dilation and stride
|
| 99 |
+
if stride > 1 and dilation > 1:
|
| 100 |
+
logger.warning(
|
| 101 |
+
"EncodecConv1d has been initialized with stride > 1 and dilation > 1"
|
| 102 |
+
f" (kernel_size={kernel_size} stride={stride}, dilation={dilation})."
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
self.conv = nn.Conv1d(in_channels, out_channels, kernel_size, stride, dilation=dilation)
|
| 106 |
+
weight_norm = nn.utils.weight_norm
|
| 107 |
+
if hasattr(nn.utils.parametrizations, "weight_norm"):
|
| 108 |
+
weight_norm = nn.utils.parametrizations.weight_norm
|
| 109 |
+
|
| 110 |
+
if self.norm_type == "weight_norm":
|
| 111 |
+
self.conv = weight_norm(self.conv)
|
| 112 |
+
elif self.norm_type == "time_group_norm":
|
| 113 |
+
self.norm = nn.GroupNorm(1, out_channels)
|
| 114 |
+
|
| 115 |
+
kernel_size = self.conv.kernel_size[0]
|
| 116 |
+
stride = torch.tensor(self.conv.stride[0], dtype=torch.int64)
|
| 117 |
+
dilation = self.conv.dilation[0]
|
| 118 |
+
|
| 119 |
+
# Effective kernel size with dilations.
|
| 120 |
+
kernel_size = torch.tensor((kernel_size - 1) * dilation + 1, dtype=torch.int64)
|
| 121 |
+
|
| 122 |
+
self.register_buffer("stride", stride, persistent=False)
|
| 123 |
+
self.register_buffer("kernel_size", kernel_size, persistent=False)
|
| 124 |
+
self.register_buffer("padding_total", kernel_size - stride, persistent=False)
|
| 125 |
+
|
| 126 |
+
def _get_extra_padding_for_conv1d(
|
| 127 |
+
self,
|
| 128 |
+
hidden_states: torch.Tensor,
|
| 129 |
+
) -> torch.Tensor:
|
| 130 |
+
"""See `pad_for_conv1d`."""
|
| 131 |
+
length = hidden_states.shape[-1]
|
| 132 |
+
n_frames = (length - self.kernel_size + self.padding_total) / self.stride + 1
|
| 133 |
+
n_frames = torch.ceil(n_frames).to(torch.int64) - 1
|
| 134 |
+
ideal_length = n_frames * self.stride + self.kernel_size - self.padding_total
|
| 135 |
+
|
| 136 |
+
return ideal_length - length
|
| 137 |
+
|
| 138 |
+
@staticmethod
|
| 139 |
+
def _pad1d(hidden_states: torch.Tensor, paddings: tuple[int, int], mode: str = "zero", value: float = 0.0):
|
| 140 |
+
"""Tiny wrapper around torch.nn.functional.pad, just to allow for reflect padding on small input.
|
| 141 |
+
If this is the case, we insert extra 0 padding to the right before the reflection happens.
|
| 142 |
+
"""
|
| 143 |
+
length = hidden_states.shape[-1]
|
| 144 |
+
padding_left, padding_right = paddings
|
| 145 |
+
if mode != "reflect":
|
| 146 |
+
return nn.functional.pad(hidden_states, paddings, mode, value)
|
| 147 |
+
|
| 148 |
+
max_pad = max(padding_left, padding_right)
|
| 149 |
+
extra_pad = 0
|
| 150 |
+
if length <= max_pad:
|
| 151 |
+
extra_pad = max_pad - length + 1
|
| 152 |
+
hidden_states = nn.functional.pad(hidden_states, (0, extra_pad))
|
| 153 |
+
padded = nn.functional.pad(hidden_states, paddings, mode, value)
|
| 154 |
+
end = padded.shape[-1] - extra_pad
|
| 155 |
+
return padded[..., :end]
|
| 156 |
+
|
| 157 |
+
def forward(self, hidden_states):
|
| 158 |
+
extra_padding = self._get_extra_padding_for_conv1d(hidden_states)
|
| 159 |
+
|
| 160 |
+
if self.causal:
|
| 161 |
+
# Left padding for causal
|
| 162 |
+
hidden_states = self._pad1d(hidden_states, (self.padding_total, extra_padding), mode=self.pad_mode)
|
| 163 |
+
else:
|
| 164 |
+
# Asymmetric padding required for odd strides
|
| 165 |
+
padding_right = self.padding_total // 2
|
| 166 |
+
padding_left = self.padding_total - padding_right
|
| 167 |
+
hidden_states = self._pad1d(
|
| 168 |
+
hidden_states, (padding_left, padding_right + extra_padding), mode=self.pad_mode
|
| 169 |
+
)
|
| 170 |
+
|
| 171 |
+
hidden_states = self.conv(hidden_states)
|
| 172 |
+
|
| 173 |
+
if self.norm_type == "time_group_norm":
|
| 174 |
+
hidden_states = self.norm(hidden_states)
|
| 175 |
+
|
| 176 |
+
return hidden_states
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
class EncodecConvTranspose1d(nn.Module):
|
| 180 |
+
"""ConvTranspose1d with asymmetric or causal padding and normalization."""
|
| 181 |
+
|
| 182 |
+
def __init__(self, config, in_channels: int, out_channels: int, kernel_size: int, stride: int = 1):
|
| 183 |
+
super().__init__()
|
| 184 |
+
self.causal = config.use_causal_conv
|
| 185 |
+
self.trim_right_ratio = config.trim_right_ratio
|
| 186 |
+
self.norm_type = config.norm_type
|
| 187 |
+
if self.norm_type not in ["weight_norm", "time_group_norm"]:
|
| 188 |
+
raise ValueError(
|
| 189 |
+
f'self.norm_type must be one of `"weight_norm"`, `"time_group_norm"`), got {self.norm_type}'
|
| 190 |
+
)
|
| 191 |
+
|
| 192 |
+
self.conv = nn.ConvTranspose1d(in_channels, out_channels, kernel_size, stride)
|
| 193 |
+
|
| 194 |
+
weight_norm = nn.utils.weight_norm
|
| 195 |
+
if hasattr(nn.utils.parametrizations, "weight_norm"):
|
| 196 |
+
weight_norm = nn.utils.parametrizations.weight_norm
|
| 197 |
+
|
| 198 |
+
if config.norm_type == "weight_norm":
|
| 199 |
+
self.conv = weight_norm(self.conv)
|
| 200 |
+
elif config.norm_type == "time_group_norm":
|
| 201 |
+
self.norm = nn.GroupNorm(1, out_channels)
|
| 202 |
+
|
| 203 |
+
if not (self.causal or self.trim_right_ratio == 1.0):
|
| 204 |
+
raise ValueError("`trim_right_ratio` != 1.0 only makes sense for causal convolutions")
|
| 205 |
+
|
| 206 |
+
def forward(self, hidden_states):
|
| 207 |
+
kernel_size = self.conv.kernel_size[0]
|
| 208 |
+
stride = self.conv.stride[0]
|
| 209 |
+
padding_total = kernel_size - stride
|
| 210 |
+
|
| 211 |
+
hidden_states = self.conv(hidden_states)
|
| 212 |
+
|
| 213 |
+
if self.norm_type == "time_group_norm":
|
| 214 |
+
hidden_states = self.norm(hidden_states)
|
| 215 |
+
|
| 216 |
+
# We will only trim fixed padding. Extra padding from `pad_for_conv1d` would be
|
| 217 |
+
# removed at the very end, when keeping only the right length for the output,
|
| 218 |
+
# as removing it here would require also passing the length at the matching layer
|
| 219 |
+
# in the encoder.
|
| 220 |
+
if self.causal:
|
| 221 |
+
# Trim the padding on the right according to the specified ratio
|
| 222 |
+
# if trim_right_ratio = 1.0, trim everything from right
|
| 223 |
+
padding_right = math.ceil(padding_total * self.trim_right_ratio)
|
| 224 |
+
else:
|
| 225 |
+
# Asymmetric padding required for odd strides
|
| 226 |
+
padding_right = padding_total // 2
|
| 227 |
+
|
| 228 |
+
padding_left = padding_total - padding_right
|
| 229 |
+
|
| 230 |
+
# unpad
|
| 231 |
+
end = hidden_states.shape[-1] - padding_right
|
| 232 |
+
hidden_states = hidden_states[..., padding_left:end]
|
| 233 |
+
return hidden_states
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
class EncodecLSTM(nn.Module):
|
| 237 |
+
"""
|
| 238 |
+
LSTM without worrying about the hidden state, nor the layout of the data. Expects input as convolutional layout.
|
| 239 |
+
"""
|
| 240 |
+
|
| 241 |
+
def __init__(self, config: EncodecConfig, dimension: int):
|
| 242 |
+
super().__init__()
|
| 243 |
+
self.lstm = nn.LSTM(dimension, dimension, config.num_lstm_layers)
|
| 244 |
+
|
| 245 |
+
def forward(self, hidden_states):
|
| 246 |
+
hidden_states = hidden_states.permute(2, 0, 1)
|
| 247 |
+
hidden_states = self.lstm(hidden_states)[0] + hidden_states
|
| 248 |
+
hidden_states = hidden_states.permute(1, 2, 0)
|
| 249 |
+
return hidden_states
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
class EncodecResnetBlock(nn.Module):
|
| 253 |
+
"""
|
| 254 |
+
Residual block from SEANet model as used by EnCodec.
|
| 255 |
+
"""
|
| 256 |
+
|
| 257 |
+
def __init__(self, config: EncodecConfig, dim: int, dilations: list[int]):
|
| 258 |
+
super().__init__()
|
| 259 |
+
kernel_sizes = (config.residual_kernel_size, 1)
|
| 260 |
+
if len(kernel_sizes) != len(dilations):
|
| 261 |
+
raise ValueError("Number of kernel sizes should match number of dilations")
|
| 262 |
+
|
| 263 |
+
hidden = dim // config.compress
|
| 264 |
+
block = []
|
| 265 |
+
for i, (kernel_size, dilation) in enumerate(zip(kernel_sizes, dilations)):
|
| 266 |
+
in_chs = dim if i == 0 else hidden
|
| 267 |
+
out_chs = dim if i == len(kernel_sizes) - 1 else hidden
|
| 268 |
+
block += [nn.ELU()]
|
| 269 |
+
block += [EncodecConv1d(config, in_chs, out_chs, kernel_size, dilation=dilation)]
|
| 270 |
+
self.block = nn.ModuleList(block)
|
| 271 |
+
|
| 272 |
+
if config.use_conv_shortcut:
|
| 273 |
+
self.shortcut = EncodecConv1d(config, dim, dim, kernel_size=1)
|
| 274 |
+
else:
|
| 275 |
+
self.shortcut = nn.Identity()
|
| 276 |
+
|
| 277 |
+
def forward(self, hidden_states):
|
| 278 |
+
residual = hidden_states
|
| 279 |
+
for layer in self.block:
|
| 280 |
+
hidden_states = layer(hidden_states)
|
| 281 |
+
|
| 282 |
+
return self.shortcut(residual) + hidden_states
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
class EncodecEncoder(nn.Module):
|
| 286 |
+
"""SEANet encoder as used by EnCodec."""
|
| 287 |
+
|
| 288 |
+
def __init__(self, config: EncodecConfig):
|
| 289 |
+
super().__init__()
|
| 290 |
+
model = [EncodecConv1d(config, config.audio_channels, config.num_filters, config.kernel_size)]
|
| 291 |
+
scaling = 1
|
| 292 |
+
|
| 293 |
+
# Downsample to raw audio scale
|
| 294 |
+
for ratio in reversed(config.upsampling_ratios):
|
| 295 |
+
current_scale = scaling * config.num_filters
|
| 296 |
+
# Add residual layers
|
| 297 |
+
for j in range(config.num_residual_layers):
|
| 298 |
+
model += [EncodecResnetBlock(config, current_scale, [config.dilation_growth_rate**j, 1])]
|
| 299 |
+
# Add downsampling layers
|
| 300 |
+
model += [nn.ELU()]
|
| 301 |
+
model += [EncodecConv1d(config, current_scale, current_scale * 2, kernel_size=ratio * 2, stride=ratio)]
|
| 302 |
+
scaling *= 2
|
| 303 |
+
|
| 304 |
+
model += [EncodecLSTM(config, scaling * config.num_filters)]
|
| 305 |
+
model += [nn.ELU()]
|
| 306 |
+
model += [EncodecConv1d(config, scaling * config.num_filters, config.hidden_size, config.last_kernel_size)]
|
| 307 |
+
|
| 308 |
+
self.layers = nn.ModuleList(model)
|
| 309 |
+
|
| 310 |
+
def forward(self, hidden_states):
|
| 311 |
+
for layer in self.layers:
|
| 312 |
+
hidden_states = layer(hidden_states)
|
| 313 |
+
return hidden_states
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
class EncodecDecoder(nn.Module):
|
| 317 |
+
"""SEANet decoder as used by EnCodec."""
|
| 318 |
+
|
| 319 |
+
def __init__(self, config: EncodecConfig):
|
| 320 |
+
super().__init__()
|
| 321 |
+
scaling = int(2 ** len(config.upsampling_ratios))
|
| 322 |
+
model = [EncodecConv1d(config, config.hidden_size, scaling * config.num_filters, config.kernel_size)]
|
| 323 |
+
|
| 324 |
+
model += [EncodecLSTM(config, scaling * config.num_filters)]
|
| 325 |
+
|
| 326 |
+
# Upsample to raw audio scale
|
| 327 |
+
for ratio in config.upsampling_ratios:
|
| 328 |
+
current_scale = scaling * config.num_filters
|
| 329 |
+
# Add upsampling layers
|
| 330 |
+
model += [nn.ELU()]
|
| 331 |
+
model += [
|
| 332 |
+
EncodecConvTranspose1d(config, current_scale, current_scale // 2, kernel_size=ratio * 2, stride=ratio)
|
| 333 |
+
]
|
| 334 |
+
# Add residual layers
|
| 335 |
+
for j in range(config.num_residual_layers):
|
| 336 |
+
model += [EncodecResnetBlock(config, current_scale // 2, (config.dilation_growth_rate**j, 1))]
|
| 337 |
+
scaling //= 2
|
| 338 |
+
|
| 339 |
+
# Add final layers
|
| 340 |
+
model += [nn.ELU()]
|
| 341 |
+
model += [EncodecConv1d(config, config.num_filters, config.audio_channels, config.last_kernel_size)]
|
| 342 |
+
self.layers = nn.ModuleList(model)
|
| 343 |
+
|
| 344 |
+
def forward(self, hidden_states):
|
| 345 |
+
for layer in self.layers:
|
| 346 |
+
hidden_states = layer(hidden_states)
|
| 347 |
+
return hidden_states
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
class EncodecEuclideanCodebook(nn.Module):
|
| 351 |
+
"""Codebook with Euclidean distance."""
|
| 352 |
+
|
| 353 |
+
def __init__(self, config: EncodecConfig):
|
| 354 |
+
super().__init__()
|
| 355 |
+
embed = torch.zeros(config.codebook_size, config.codebook_dim)
|
| 356 |
+
|
| 357 |
+
self.codebook_size = config.codebook_size
|
| 358 |
+
|
| 359 |
+
self.register_buffer("inited", torch.Tensor([True]))
|
| 360 |
+
self.register_buffer("cluster_size", torch.zeros(config.codebook_size))
|
| 361 |
+
self.register_buffer("embed", embed)
|
| 362 |
+
self.register_buffer("embed_avg", embed.clone())
|
| 363 |
+
|
| 364 |
+
def quantize(self, hidden_states):
|
| 365 |
+
embed = self.embed.t()
|
| 366 |
+
scaled_states = hidden_states.pow(2).sum(1, keepdim=True)
|
| 367 |
+
dist = -(scaled_states - 2 * hidden_states @ embed + embed.pow(2).sum(0, keepdim=True))
|
| 368 |
+
embed_ind = dist.max(dim=-1).indices
|
| 369 |
+
return embed_ind
|
| 370 |
+
|
| 371 |
+
def encode(self, hidden_states):
|
| 372 |
+
shape = hidden_states.shape
|
| 373 |
+
# pre-process
|
| 374 |
+
hidden_states = hidden_states.reshape((-1, shape[-1]))
|
| 375 |
+
# quantize
|
| 376 |
+
embed_ind = self.quantize(hidden_states)
|
| 377 |
+
# post-process
|
| 378 |
+
embed_ind = embed_ind.view(*shape[:-1])
|
| 379 |
+
return embed_ind
|
| 380 |
+
|
| 381 |
+
def decode(self, embed_ind):
|
| 382 |
+
quantize = nn.functional.embedding(embed_ind, self.embed)
|
| 383 |
+
return quantize
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
class EncodecVectorQuantization(nn.Module):
|
| 387 |
+
"""
|
| 388 |
+
Vector quantization implementation. Currently supports only euclidean distance.
|
| 389 |
+
"""
|
| 390 |
+
|
| 391 |
+
def __init__(self, config: EncodecConfig):
|
| 392 |
+
super().__init__()
|
| 393 |
+
self.codebook = EncodecEuclideanCodebook(config)
|
| 394 |
+
|
| 395 |
+
def encode(self, hidden_states):
|
| 396 |
+
hidden_states = hidden_states.permute(0, 2, 1)
|
| 397 |
+
embed_in = self.codebook.encode(hidden_states)
|
| 398 |
+
return embed_in
|
| 399 |
+
|
| 400 |
+
def decode(self, embed_ind):
|
| 401 |
+
quantize = self.codebook.decode(embed_ind)
|
| 402 |
+
quantize = quantize.permute(0, 2, 1)
|
| 403 |
+
return quantize
|
| 404 |
+
|
| 405 |
+
|
| 406 |
+
class EncodecResidualVectorQuantizer(nn.Module):
|
| 407 |
+
"""Residual Vector Quantizer."""
|
| 408 |
+
|
| 409 |
+
def __init__(self, config: EncodecConfig):
|
| 410 |
+
super().__init__()
|
| 411 |
+
self.codebook_size = config.codebook_size
|
| 412 |
+
self.frame_rate = config.frame_rate
|
| 413 |
+
self.num_quantizers = config.num_quantizers
|
| 414 |
+
self.layers = nn.ModuleList([EncodecVectorQuantization(config) for _ in range(config.num_quantizers)])
|
| 415 |
+
|
| 416 |
+
def get_num_quantizers_for_bandwidth(self, bandwidth: float | None = None) -> int:
|
| 417 |
+
"""Return num_quantizers based on specified target bandwidth."""
|
| 418 |
+
bw_per_q = math.log2(self.codebook_size) * self.frame_rate
|
| 419 |
+
num_quantizers = self.num_quantizers
|
| 420 |
+
if bandwidth is not None and bandwidth > 0.0:
|
| 421 |
+
num_quantizers = int(max(1, math.floor(bandwidth * 1000 / bw_per_q)))
|
| 422 |
+
return num_quantizers
|
| 423 |
+
|
| 424 |
+
def encode(self, embeddings: torch.Tensor, bandwidth: float | None = None) -> torch.Tensor:
|
| 425 |
+
"""
|
| 426 |
+
Encode a given input tensor with the specified frame rate at the given bandwidth. The RVQ encode method sets
|
| 427 |
+
the appropriate number of quantizers to use and returns indices for each quantizer.
|
| 428 |
+
"""
|
| 429 |
+
num_quantizers = self.get_num_quantizers_for_bandwidth(bandwidth)
|
| 430 |
+
residual = embeddings
|
| 431 |
+
all_indices = []
|
| 432 |
+
for layer in self.layers[:num_quantizers]:
|
| 433 |
+
indices = layer.encode(residual)
|
| 434 |
+
quantized = layer.decode(indices)
|
| 435 |
+
residual = residual - quantized
|
| 436 |
+
all_indices.append(indices)
|
| 437 |
+
out_indices = torch.stack(all_indices)
|
| 438 |
+
return out_indices
|
| 439 |
+
|
| 440 |
+
def decode(self, codes: torch.Tensor) -> torch.Tensor:
|
| 441 |
+
"""Decode the given codes to the quantized representation."""
|
| 442 |
+
quantized_out = torch.tensor(0.0, device=codes.device)
|
| 443 |
+
for i, indices in enumerate(codes):
|
| 444 |
+
layer = self.layers[i]
|
| 445 |
+
quantized = layer.decode(indices)
|
| 446 |
+
quantized_out = quantized_out + quantized
|
| 447 |
+
return quantized_out
|
| 448 |
+
|
| 449 |
+
|
| 450 |
+
@auto_docstring
|
| 451 |
+
class EncodecPreTrainedModel(PreTrainedAudioTokenizerBase):
|
| 452 |
+
config: EncodecConfig
|
| 453 |
+
base_model_prefix = "encodec"
|
| 454 |
+
main_input_name = "input_values"
|
| 455 |
+
|
| 456 |
+
@torch.no_grad()
|
| 457 |
+
def _init_weights(self, module):
|
| 458 |
+
"""Initialize the weights"""
|
| 459 |
+
if isinstance(module, nn.GroupNorm):
|
| 460 |
+
init.zeros_(module.bias)
|
| 461 |
+
init.ones_(module.weight)
|
| 462 |
+
elif isinstance(module, nn.Conv1d):
|
| 463 |
+
init.kaiming_normal_(module.weight)
|
| 464 |
+
if module.bias is not None:
|
| 465 |
+
k = math.sqrt(module.groups / (module.in_channels * module.kernel_size[0]))
|
| 466 |
+
init.uniform_(module.bias, a=-k, b=k)
|
| 467 |
+
elif isinstance(module, nn.ConvTranspose1d):
|
| 468 |
+
module.reset_parameters()
|
| 469 |
+
elif isinstance(module, nn.LSTM):
|
| 470 |
+
for name, param in module.named_parameters():
|
| 471 |
+
if "weight" in name:
|
| 472 |
+
init.xavier_uniform_(param)
|
| 473 |
+
elif "bias" in name:
|
| 474 |
+
init.constant_(param, 0.0)
|
| 475 |
+
elif isinstance(module, EncodecConv1d):
|
| 476 |
+
kernel_size = module.conv.kernel_size[0]
|
| 477 |
+
stride = torch.tensor(module.conv.stride[0], dtype=torch.int64)
|
| 478 |
+
dilation = module.conv.dilation[0]
|
| 479 |
+
# Effective kernel size with dilations.
|
| 480 |
+
kernel_size = torch.tensor((kernel_size - 1) * dilation + 1, dtype=torch.int64)
|
| 481 |
+
init.copy_(module.stride, stride)
|
| 482 |
+
init.copy_(module.kernel_size, kernel_size)
|
| 483 |
+
init.copy_(module.padding_total, kernel_size - stride)
|
| 484 |
+
elif isinstance(module, EncodecEuclideanCodebook):
|
| 485 |
+
init.copy_(module.inited, torch.Tensor([True]))
|
| 486 |
+
init.zeros_(module.cluster_size)
|
| 487 |
+
init.zeros_(module.embed)
|
| 488 |
+
init.zeros_(module.embed_avg)
|
| 489 |
+
|
| 490 |
+
|
| 491 |
+
@auto_docstring(
|
| 492 |
+
custom_intro="""
|
| 493 |
+
The EnCodec neural audio codec model.
|
| 494 |
+
"""
|
| 495 |
+
)
|
| 496 |
+
class EncodecModel(EncodecPreTrainedModel):
|
| 497 |
+
def __init__(self, config: EncodecConfig):
|
| 498 |
+
super().__init__(config)
|
| 499 |
+
self.config = config
|
| 500 |
+
|
| 501 |
+
self.encoder = EncodecEncoder(config)
|
| 502 |
+
self.decoder = EncodecDecoder(config)
|
| 503 |
+
|
| 504 |
+
self.quantizer = EncodecResidualVectorQuantizer(config)
|
| 505 |
+
|
| 506 |
+
self.bits_per_codebook = int(math.log2(self.config.codebook_size))
|
| 507 |
+
if 2**self.bits_per_codebook != self.config.codebook_size:
|
| 508 |
+
raise ValueError("The codebook_size must be a power of 2.")
|
| 509 |
+
|
| 510 |
+
# Initialize weights and apply final processing
|
| 511 |
+
self.post_init()
|
| 512 |
+
|
| 513 |
+
def _encode_frame(self, input_values: torch.Tensor, bandwidth: float) -> tuple[torch.Tensor, torch.Tensor | None]:
|
| 514 |
+
"""
|
| 515 |
+
Encodes the given input using the underlying VQVAE. If `config.normalize` is set to `True` the input is first
|
| 516 |
+
normalized. The padding mask is required to compute the correct scale.
|
| 517 |
+
"""
|
| 518 |
+
length = input_values.shape[-1]
|
| 519 |
+
duration = length / self.config.sampling_rate
|
| 520 |
+
|
| 521 |
+
if self.config.chunk_length_s is not None and duration > 1e-5 + self.config.chunk_length_s:
|
| 522 |
+
raise RuntimeError(f"Duration of frame ({duration}) is longer than chunk {self.config.chunk_length_s}")
|
| 523 |
+
|
| 524 |
+
scale = None
|
| 525 |
+
if self.config.normalize:
|
| 526 |
+
mono = torch.sum(input_values, 1, keepdim=True) / input_values.shape[1]
|
| 527 |
+
scale = mono.pow(2).mean(dim=-1, keepdim=True).sqrt() + 1e-8
|
| 528 |
+
input_values = input_values / scale
|
| 529 |
+
scale = scale.view(-1, 1)
|
| 530 |
+
|
| 531 |
+
embeddings = self.encoder(input_values)
|
| 532 |
+
codes = self.quantizer.encode(embeddings, bandwidth)
|
| 533 |
+
codes = codes.transpose(0, 1)
|
| 534 |
+
return codes, scale
|
| 535 |
+
|
| 536 |
+
def encode(
|
| 537 |
+
self,
|
| 538 |
+
input_values: torch.Tensor,
|
| 539 |
+
padding_mask: torch.Tensor | None = None,
|
| 540 |
+
bandwidth: float | None = None,
|
| 541 |
+
return_dict: bool | None = None,
|
| 542 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, int] | EncodecEncoderOutput:
|
| 543 |
+
"""
|
| 544 |
+
Encodes the input audio waveform into discrete codes of shape
|
| 545 |
+
`(nb_frames, batch_size, nb_quantizers, frame_len)`.
|
| 546 |
+
|
| 547 |
+
- `nb_frames=1` if `self.config.chunk_length=None` (as the encoder is applied on the full audio), which is the
|
| 548 |
+
case for the 24kHz model. Otherwise, `nb_frames=ceil(input_length/self.config.chunk_stride)`, which is the case
|
| 549 |
+
for the 48kHz model.
|
| 550 |
+
- `frame_len` is the length of each frame, which is equal to `ceil(input_length/self.config.hop_length)` if
|
| 551 |
+
`self.config.chunk_length=None` (e.g., for the 24kHz model). Otherwise, if `self.config.chunk_length` is
|
| 552 |
+
defined, `frame_len=self.config.chunk_length/self.config.hop_length`, e.g., the case for the 48kHz model with
|
| 553 |
+
`frame_len=150`.
|
| 554 |
+
|
| 555 |
+
Args:
|
| 556 |
+
input_values (`torch.Tensor` of shape `(batch_size, channels, sequence_length)`):
|
| 557 |
+
Float values of the input audio waveform.
|
| 558 |
+
padding_mask (`torch.Tensor` of shape `(batch_size, channels, sequence_length)`):
|
| 559 |
+
Padding mask used to pad the `input_values`.
|
| 560 |
+
bandwidth (`float`, *optional*):
|
| 561 |
+
The target bandwidth. Must be one of `config.target_bandwidths`. If `None`, uses the smallest possible
|
| 562 |
+
bandwidth. bandwidth is represented as a thousandth of what it is, e.g. 6kbps bandwidth is represented
|
| 563 |
+
as bandwidth == 6.0
|
| 564 |
+
|
| 565 |
+
Returns:
|
| 566 |
+
EncodecEncoderOutput dict or a tuple containing:
|
| 567 |
+
- audio_codes (`torch.LongTensor` of shape `(nb_frames, batch_size, nb_quantizers, frame_len)`, *optional*),
|
| 568 |
+
- audio_scales (list of length `nb_frames` of `torch.Tensor` of shape `(batch_size, 1)`, *optional*),
|
| 569 |
+
- last_frame_pad_length (`int`, *optional*).
|
| 570 |
+
"""
|
| 571 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 572 |
+
|
| 573 |
+
if bandwidth is None:
|
| 574 |
+
bandwidth = self.config.target_bandwidths[0]
|
| 575 |
+
if bandwidth not in self.config.target_bandwidths:
|
| 576 |
+
raise ValueError(
|
| 577 |
+
f"This model doesn't support the bandwidth {bandwidth}. Select one of {self.config.target_bandwidths}."
|
| 578 |
+
)
|
| 579 |
+
|
| 580 |
+
_, channels, input_length = input_values.shape
|
| 581 |
+
|
| 582 |
+
if channels < 1 or channels > 2:
|
| 583 |
+
raise ValueError(f"Number of audio channels must be 1 or 2, but got {channels}")
|
| 584 |
+
|
| 585 |
+
chunk_length = self.config.chunk_length
|
| 586 |
+
if chunk_length is None:
|
| 587 |
+
chunk_length = input_length
|
| 588 |
+
stride = input_length
|
| 589 |
+
else:
|
| 590 |
+
stride = self.config.chunk_stride
|
| 591 |
+
|
| 592 |
+
if padding_mask is None:
|
| 593 |
+
padding_mask = torch.ones_like(input_values).bool()
|
| 594 |
+
else:
|
| 595 |
+
padding_mask = padding_mask.view(padding_mask.shape[0], -1, padding_mask.shape[-1])
|
| 596 |
+
|
| 597 |
+
encoded_frames = []
|
| 598 |
+
scales = []
|
| 599 |
+
for offset in range(0, input_length, stride):
|
| 600 |
+
mask = padding_mask[..., offset : offset + chunk_length].bool()
|
| 601 |
+
frame = mask * input_values[..., offset : offset + chunk_length]
|
| 602 |
+
encoded_frame, scale = self._encode_frame(frame, bandwidth)
|
| 603 |
+
encoded_frames.append(encoded_frame)
|
| 604 |
+
scales.append(scale)
|
| 605 |
+
|
| 606 |
+
# pad last frame (if necessary) to be able to apply `torch.stack`
|
| 607 |
+
last_frame_pad_length = encoded_frames[0].shape[-1] - encoded_frames[-1].shape[-1]
|
| 608 |
+
if last_frame_pad_length > 0:
|
| 609 |
+
last_frame = nn.functional.pad(encoded_frames[-1], (0, last_frame_pad_length), value=0)
|
| 610 |
+
encoded_frames[-1] = last_frame
|
| 611 |
+
encoded_frames = torch.stack(encoded_frames)
|
| 612 |
+
|
| 613 |
+
if not return_dict:
|
| 614 |
+
return (encoded_frames, scales, last_frame_pad_length)
|
| 615 |
+
return EncodecEncoderOutput(encoded_frames, scales, last_frame_pad_length)
|
| 616 |
+
|
| 617 |
+
@staticmethod
|
| 618 |
+
def _linear_overlap_add(frames: list[torch.Tensor], stride: int):
|
| 619 |
+
# Generic overlap add, with linear fade-in/fade-out, supporting complex scenario
|
| 620 |
+
# e.g., more than 2 frames per position.
|
| 621 |
+
# The core idea is to use a weight function that is a triangle,
|
| 622 |
+
# with a maximum value at the middle of the chunk.
|
| 623 |
+
# We use this weighting when summing the frames, and divide by the sum of weights
|
| 624 |
+
# for each positions at the end. Thus:
|
| 625 |
+
# - if a frame is the only one to cover a position, the weighting is a no-op.
|
| 626 |
+
# - if 2 frames cover a position:
|
| 627 |
+
# ... ...
|
| 628 |
+
# / \/ \
|
| 629 |
+
# / /\ \
|
| 630 |
+
# S T , i.e. S offset of second frame starts, T end of first frame.
|
| 631 |
+
# Then the weight function for each one is: (t - S), (T - t), with `t` a given offset.
|
| 632 |
+
# After the final normalization, the weight of the second frame at position `t` is
|
| 633 |
+
# (t - S) / (t - S + (T - t)) = (t - S) / (T - S), which is exactly what we want.
|
| 634 |
+
#
|
| 635 |
+
# - if more than 2 frames overlap at a given point, we hope that by induction
|
| 636 |
+
# something sensible happens.
|
| 637 |
+
if len(frames) == 0:
|
| 638 |
+
raise ValueError("`frames` cannot be an empty list.")
|
| 639 |
+
|
| 640 |
+
device = frames[0].device
|
| 641 |
+
dtype = frames[0].dtype
|
| 642 |
+
shape = frames[0].shape[:-1]
|
| 643 |
+
total_size = stride * (len(frames) - 1) + frames[-1].shape[-1]
|
| 644 |
+
|
| 645 |
+
frame_length = frames[0].shape[-1]
|
| 646 |
+
time_vec = torch.linspace(0, 1, frame_length + 2, device=device, dtype=dtype)[1:-1]
|
| 647 |
+
weight = 0.5 - (time_vec - 0.5).abs()
|
| 648 |
+
|
| 649 |
+
sum_weight = torch.zeros(total_size, device=device, dtype=dtype)
|
| 650 |
+
out = torch.zeros(*shape, total_size, device=device, dtype=dtype)
|
| 651 |
+
offset: int = 0
|
| 652 |
+
|
| 653 |
+
for frame in frames:
|
| 654 |
+
frame_length = frame.shape[-1]
|
| 655 |
+
out[..., offset : offset + frame_length] += weight[:frame_length] * frame
|
| 656 |
+
sum_weight[offset : offset + frame_length] += weight[:frame_length]
|
| 657 |
+
offset += stride
|
| 658 |
+
|
| 659 |
+
if sum_weight.min() == 0:
|
| 660 |
+
raise ValueError(f"`sum_weight` minimum element must be bigger than zero: {sum_weight}`")
|
| 661 |
+
|
| 662 |
+
return out / sum_weight
|
| 663 |
+
|
| 664 |
+
def _decode_frame(self, codes: torch.Tensor, scale: torch.Tensor | None = None) -> torch.Tensor:
|
| 665 |
+
codes = codes.transpose(0, 1)
|
| 666 |
+
embeddings = self.quantizer.decode(codes)
|
| 667 |
+
outputs = self.decoder(embeddings)
|
| 668 |
+
if scale is not None:
|
| 669 |
+
outputs = outputs * scale.view(-1, 1, 1)
|
| 670 |
+
return outputs
|
| 671 |
+
|
| 672 |
+
def decode(
|
| 673 |
+
self,
|
| 674 |
+
audio_codes: torch.LongTensor,
|
| 675 |
+
audio_scales: torch.Tensor,
|
| 676 |
+
padding_mask: torch.Tensor | None = None,
|
| 677 |
+
return_dict: bool | None = None,
|
| 678 |
+
last_frame_pad_length: int | None = 0,
|
| 679 |
+
) -> tuple[torch.Tensor, torch.Tensor] | EncodecDecoderOutput:
|
| 680 |
+
"""
|
| 681 |
+
Decodes the given frames into an output audio waveform.
|
| 682 |
+
|
| 683 |
+
Note that the output might be a bit bigger than the input. In that case, any extra steps at the end can be
|
| 684 |
+
trimmed.
|
| 685 |
+
|
| 686 |
+
Args:
|
| 687 |
+
audio_codes (`torch.LongTensor` of shape `(nb_frames, batch_size, nb_quantizers, frame_len)`, *optional*):
|
| 688 |
+
Discrete code embeddings computed using `model.encode`.
|
| 689 |
+
audio_scales (list of length `nb_frames` of `torch.Tensor` of shape `(batch_size, 1)`, *optional*):
|
| 690 |
+
Scaling factor for each `audio_codes` input.
|
| 691 |
+
padding_mask (`torch.Tensor` of shape `(channels, sequence_length)`):
|
| 692 |
+
Padding mask used to pad the `input_values`.
|
| 693 |
+
return_dict (`bool`, *optional*):
|
| 694 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 695 |
+
last_frame_pad_length (`int`, *optional*):
|
| 696 |
+
Integer representing the length of the padding in the last frame, which is removed during decoding.
|
| 697 |
+
|
| 698 |
+
"""
|
| 699 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 700 |
+
|
| 701 |
+
chunk_length = self.config.chunk_length
|
| 702 |
+
if chunk_length is None:
|
| 703 |
+
if len(audio_codes) != 1:
|
| 704 |
+
raise ValueError(f"Expected one frame, got {len(audio_codes)}")
|
| 705 |
+
frame = audio_codes[0]
|
| 706 |
+
if last_frame_pad_length > 0:
|
| 707 |
+
frame = frame[..., :-last_frame_pad_length]
|
| 708 |
+
audio_values = self._decode_frame(frame, audio_scales[0])
|
| 709 |
+
else:
|
| 710 |
+
decoded_frames = []
|
| 711 |
+
for i, (frame, scale) in enumerate(zip(audio_codes, audio_scales)):
|
| 712 |
+
if i == len(audio_codes) - 1 and last_frame_pad_length > 0:
|
| 713 |
+
frame = frame[..., :-last_frame_pad_length]
|
| 714 |
+
frames = self._decode_frame(frame, scale)
|
| 715 |
+
decoded_frames.append(frames)
|
| 716 |
+
|
| 717 |
+
audio_values = self._linear_overlap_add(decoded_frames, self.config.chunk_stride or 1)
|
| 718 |
+
|
| 719 |
+
# truncate based on padding mask
|
| 720 |
+
if padding_mask is not None and padding_mask.shape[-1] < audio_values.shape[-1]:
|
| 721 |
+
audio_values = audio_values[..., : padding_mask.shape[-1]]
|
| 722 |
+
|
| 723 |
+
if not return_dict:
|
| 724 |
+
return (audio_values,)
|
| 725 |
+
return EncodecDecoderOutput(audio_values)
|
| 726 |
+
|
| 727 |
+
@auto_docstring
|
| 728 |
+
def forward(
|
| 729 |
+
self,
|
| 730 |
+
input_values: torch.FloatTensor,
|
| 731 |
+
padding_mask: torch.BoolTensor | None = None,
|
| 732 |
+
bandwidth: float | None = None,
|
| 733 |
+
audio_codes: torch.LongTensor | None = None,
|
| 734 |
+
audio_scales: torch.Tensor | None = None,
|
| 735 |
+
return_dict: bool | None = None,
|
| 736 |
+
last_frame_pad_length: int | None = 0,
|
| 737 |
+
) -> tuple[torch.Tensor, torch.Tensor] | EncodecOutput:
|
| 738 |
+
r"""
|
| 739 |
+
input_values (`torch.FloatTensor` of shape `(batch_size, channels, sequence_length)`, *optional*):
|
| 740 |
+
Raw audio input converted to Float and padded to the appropriate length in order to be encoded using chunks
|
| 741 |
+
of length self.chunk_length and a stride of `config.chunk_stride`.
|
| 742 |
+
padding_mask (`torch.BoolTensor` of shape `(batch_size, channels, sequence_length)`, *optional*):
|
| 743 |
+
Mask to avoid computing scaling factors on padding token indices (can we avoid computing conv on these+).
|
| 744 |
+
Mask values selected in `[0, 1]`:
|
| 745 |
+
|
| 746 |
+
- 1 for tokens that are **not masked**,
|
| 747 |
+
- 0 for tokens that are **masked**.
|
| 748 |
+
|
| 749 |
+
<Tip warning={true}>
|
| 750 |
+
|
| 751 |
+
`padding_mask` should always be passed, unless the input was truncated or not padded. This is because in
|
| 752 |
+
order to process tensors effectively, the input audio should be padded so that `input_length % stride =
|
| 753 |
+
step` with `step = chunk_length-stride`. This ensures that all chunks are of the same shape
|
| 754 |
+
|
| 755 |
+
</Tip>
|
| 756 |
+
bandwidth (`float`, *optional*):
|
| 757 |
+
The target bandwidth. Must be one of `config.target_bandwidths`. If `None`, uses the smallest possible
|
| 758 |
+
bandwidth. bandwidth is represented as a thousandth of what it is, e.g. 6kbps bandwidth is represented as
|
| 759 |
+
`bandwidth == 6.0`
|
| 760 |
+
audio_codes (`torch.LongTensor` of shape `(nb_frames, batch_size, nb_quantizers, frame_len)`, *optional*):
|
| 761 |
+
Discrete code embeddings computed using `model.encode`.
|
| 762 |
+
audio_scales (list of length `nb_frames` of `torch.Tensor` of shape `(batch_size, 1)`, *optional*):
|
| 763 |
+
Scaling factor for each `audio_codes` input.
|
| 764 |
+
return_dict (`bool`, *optional*):
|
| 765 |
+
Whether to return outputs as a dict.
|
| 766 |
+
last_frame_pad_length (`int`, *optional*):
|
| 767 |
+
The length of the padding in the last frame, if any. This is used to ensure that the encoded frames can be
|
| 768 |
+
outputted as a tensor. This value should be passed during decoding to ensure padding is removed from the
|
| 769 |
+
encoded frames.
|
| 770 |
+
|
| 771 |
+
Examples:
|
| 772 |
+
|
| 773 |
+
```python
|
| 774 |
+
>>> from datasets import load_dataset
|
| 775 |
+
>>> from transformers import AutoProcessor, EncodecModel
|
| 776 |
+
|
| 777 |
+
>>> dataset = load_dataset("hf-internal-testing/ashraq-esc50-1-dog-example")
|
| 778 |
+
>>> audio_sample = dataset["train"]["audio"][0]["array"]
|
| 779 |
+
|
| 780 |
+
>>> model_id = "facebook/encodec_24khz"
|
| 781 |
+
>>> model = EncodecModel.from_pretrained(model_id)
|
| 782 |
+
>>> processor = AutoProcessor.from_pretrained(model_id)
|
| 783 |
+
|
| 784 |
+
>>> inputs = processor(raw_audio=audio_sample, return_tensors="pt")
|
| 785 |
+
|
| 786 |
+
>>> outputs = model(**inputs)
|
| 787 |
+
>>> audio_codes = outputs.audio_codes
|
| 788 |
+
>>> audio_values = outputs.audio_values
|
| 789 |
+
```"""
|
| 790 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 791 |
+
|
| 792 |
+
if padding_mask is None:
|
| 793 |
+
padding_mask = torch.ones_like(input_values).bool()
|
| 794 |
+
else:
|
| 795 |
+
# ensure that channel dimension is present
|
| 796 |
+
padding_mask = padding_mask.view(padding_mask.shape[0], -1, padding_mask.shape[-1])
|
| 797 |
+
|
| 798 |
+
if audio_codes is not None and audio_scales is None:
|
| 799 |
+
raise ValueError("You specified `audio_codes` but did not specify the `audio_scales`")
|
| 800 |
+
|
| 801 |
+
if audio_scales is not None and audio_codes is None:
|
| 802 |
+
raise ValueError("You specified `audio_scales` but did not specify the `audio_codes`")
|
| 803 |
+
|
| 804 |
+
if audio_scales is None and audio_codes is None:
|
| 805 |
+
audio_codes, audio_scales, last_frame_pad_length = self.encode(
|
| 806 |
+
input_values, padding_mask, bandwidth, False
|
| 807 |
+
)
|
| 808 |
+
|
| 809 |
+
audio_values = self.decode(
|
| 810 |
+
audio_codes,
|
| 811 |
+
audio_scales,
|
| 812 |
+
padding_mask,
|
| 813 |
+
return_dict=return_dict,
|
| 814 |
+
last_frame_pad_length=last_frame_pad_length,
|
| 815 |
+
)[0]
|
| 816 |
+
if not return_dict:
|
| 817 |
+
return (audio_codes, audio_values)
|
| 818 |
+
|
| 819 |
+
return EncodecOutput(audio_codes=audio_codes, audio_values=audio_values)
|
| 820 |
+
|
| 821 |
+
|
| 822 |
+
__all__ = ["EncodecModel", "EncodecPreTrainedModel"]
|
third_party/transformers/src/transformers/models/herbert/__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_herbert import *
|
| 22 |
+
else:
|
| 23 |
+
import sys
|
| 24 |
+
|
| 25 |
+
_file = globals()["__file__"]
|
| 26 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/herbert/tokenization_herbert.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The Google AI Language Team Authors, Allegro.pl, Facebook Inc. and the HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
from tokenizers import Tokenizer, decoders, normalizers, pre_tokenizers, processors
|
| 17 |
+
from tokenizers.models import BPE
|
| 18 |
+
|
| 19 |
+
from ...tokenization_utils_tokenizers import TokenizersBackend
|
| 20 |
+
from ...utils import logging
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
logger = logging.get_logger(__name__)
|
| 24 |
+
|
| 25 |
+
VOCAB_FILES_NAMES = {"vocab_file": "vocab.json", "merges_file": "merges.txt"}
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
class HerbertTokenizer(TokenizersBackend):
|
| 29 |
+
"""
|
| 30 |
+
Construct a BPE tokenizer for HerBERT (backed by HuggingFace's tokenizers library).
|
| 31 |
+
|
| 32 |
+
Peculiarities:
|
| 33 |
+
|
| 34 |
+
- uses BERT's pre-tokenizer: BertPreTokenizer splits tokens on spaces, and also on punctuation. Each occurrence of
|
| 35 |
+
a punctuation character will be treated separately.
|
| 36 |
+
|
| 37 |
+
This tokenizer inherits from [`TokenizersBackend`] which contains most of the methods. Users should refer to the
|
| 38 |
+
superclass for more information regarding methods.
|
| 39 |
+
|
| 40 |
+
Args:
|
| 41 |
+
vocab_file (`str`):
|
| 42 |
+
Path to the vocabulary file.
|
| 43 |
+
merges_file (`str`):
|
| 44 |
+
Path to the merges file.
|
| 45 |
+
cls_token (`str`, *optional*, defaults to `"<s>"`):
|
| 46 |
+
The classifier token.
|
| 47 |
+
unk_token (`str`, *optional*, defaults to `"<unk>"`):
|
| 48 |
+
The unknown token.
|
| 49 |
+
pad_token (`str`, *optional*, defaults to `"<pad>"`):
|
| 50 |
+
The padding token.
|
| 51 |
+
mask_token (`str`, *optional*, defaults to `"<mask>"`):
|
| 52 |
+
The mask token.
|
| 53 |
+
sep_token (`str`, *optional*, defaults to `"</s>"`):
|
| 54 |
+
The separator token.
|
| 55 |
+
vocab (`str`, `dict` or `list`, *optional*):
|
| 56 |
+
Custom vocabulary dictionary.
|
| 57 |
+
merges (`str` or `list[str]`, *optional*):
|
| 58 |
+
Custom merges list.
|
| 59 |
+
"""
|
| 60 |
+
|
| 61 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 62 |
+
model_input_names = ["input_ids", "attention_mask"]
|
| 63 |
+
model = BPE
|
| 64 |
+
|
| 65 |
+
def __init__(
|
| 66 |
+
self,
|
| 67 |
+
vocab: str | dict[str, int] | None = None,
|
| 68 |
+
merges: str | list[str] | None = None,
|
| 69 |
+
cls_token: str = "<s>",
|
| 70 |
+
unk_token: str = "<unk>",
|
| 71 |
+
pad_token: str = "<pad>",
|
| 72 |
+
mask_token: str = "<mask>",
|
| 73 |
+
sep_token: str = "</s>",
|
| 74 |
+
vocab_file: str | None = None,
|
| 75 |
+
merges_file: str | None = None,
|
| 76 |
+
**kwargs,
|
| 77 |
+
):
|
| 78 |
+
self._vocab = vocab if vocab is not None else {str(unk_token): 0}
|
| 79 |
+
self._merges = merges or []
|
| 80 |
+
self._tokenizer = Tokenizer(
|
| 81 |
+
BPE(
|
| 82 |
+
vocab=self._vocab,
|
| 83 |
+
merges=self._merges,
|
| 84 |
+
dropout=None,
|
| 85 |
+
unk_token=str(unk_token),
|
| 86 |
+
end_of_word_suffix="</w>",
|
| 87 |
+
)
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
self._tokenizer.normalizer = normalizers.BertNormalizer(
|
| 91 |
+
lowercase=False, strip_accents=False, clean_text=True, handle_chinese_chars=True
|
| 92 |
+
)
|
| 93 |
+
self._tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
|
| 94 |
+
self._tokenizer.decoder = decoders.BPEDecoder(suffix="</w>")
|
| 95 |
+
|
| 96 |
+
super().__init__(
|
| 97 |
+
cls_token=cls_token,
|
| 98 |
+
unk_token=unk_token,
|
| 99 |
+
pad_token=pad_token,
|
| 100 |
+
mask_token=mask_token,
|
| 101 |
+
sep_token=sep_token,
|
| 102 |
+
**kwargs,
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
self._tokenizer.post_processor = processors.BertProcessing(
|
| 106 |
+
sep=(self.sep_token, 2),
|
| 107 |
+
cls=(self.cls_token, 0),
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
__all__ = ["HerbertTokenizer"]
|
third_party/transformers/src/transformers/models/maskformer/__init__.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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_maskformer import *
|
| 22 |
+
from .configuration_maskformer_swin import *
|
| 23 |
+
from .feature_extraction_maskformer import *
|
| 24 |
+
from .image_processing_maskformer import *
|
| 25 |
+
from .image_processing_pil_maskformer import *
|
| 26 |
+
from .modeling_maskformer import *
|
| 27 |
+
from .modeling_maskformer_swin import *
|
| 28 |
+
else:
|
| 29 |
+
import sys
|
| 30 |
+
|
| 31 |
+
_file = globals()["__file__"]
|
| 32 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/maskformer/configuration_maskformer.py
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/maskformer/modular_maskformer.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_maskformer.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2022 Meta Platforms, Inc.s and The HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
from huggingface_hub.dataclasses import strict
|
| 21 |
+
|
| 22 |
+
from ...backbone_utils import consolidate_backbone_kwargs_to_config
|
| 23 |
+
from ...configuration_utils import PreTrainedConfig
|
| 24 |
+
from ...utils import auto_docstring, logging
|
| 25 |
+
from ..auto import CONFIG_MAPPING, AutoConfig
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
logger = logging.get_logger(__name__)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
@auto_docstring(checkpoint="facebook/maskformer-swin-base-ade")
|
| 32 |
+
@strict
|
| 33 |
+
class MaskFormerDetrConfig(PreTrainedConfig):
|
| 34 |
+
r"""
|
| 35 |
+
num_queries (`int`, *optional*, defaults to 100):
|
| 36 |
+
Number of object queries, i.e. detection slots. This is the maximal number of objects
|
| 37 |
+
[`ConditionalDetrModel`] can detect in a single image. For COCO, we recommend 100 queries.
|
| 38 |
+
position_embedding_type (`str`, *optional*, defaults to `"sine"`):
|
| 39 |
+
Type of position embeddings to be used on top of the image features. One of `"sine"` or `"learned"`.
|
| 40 |
+
dilation (`bool`, *optional*, defaults to `False`):
|
| 41 |
+
Whether to replace stride with dilation in the last convolutional block (DC5). Only supported when
|
| 42 |
+
`use_timm_backbone` = `True`.
|
| 43 |
+
|
| 44 |
+
Examples:
|
| 45 |
+
|
| 46 |
+
```python
|
| 47 |
+
>>> from transformers import MaskFormerDetrConfig, MaskFormerDetrModel
|
| 48 |
+
|
| 49 |
+
>>> # Initializing a MASK_FORMER_DETR facebook/mask_former_detr-resnet-50 style configuration
|
| 50 |
+
>>> configuration = MaskFormerDetrConfig()
|
| 51 |
+
|
| 52 |
+
>>> # Initializing a model (with random weights) from the facebook/mask_former_detr-resnet-50 style configuration
|
| 53 |
+
>>> model = MaskFormerDetrModel(configuration)
|
| 54 |
+
|
| 55 |
+
>>> # Accessing the model configuration
|
| 56 |
+
>>> configuration = model.config
|
| 57 |
+
```"""
|
| 58 |
+
|
| 59 |
+
model_type = "detr"
|
| 60 |
+
sub_configs = {"backbone_config": AutoConfig}
|
| 61 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 62 |
+
attribute_map = {
|
| 63 |
+
"hidden_size": "d_model",
|
| 64 |
+
"num_attention_heads": "encoder_attention_heads",
|
| 65 |
+
"num_hidden_layers": "encoder_layers",
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
backbone_config: dict | PreTrainedConfig | None = None
|
| 69 |
+
num_channels: int = 3
|
| 70 |
+
num_queries: int = 100
|
| 71 |
+
encoder_layers: int = 6
|
| 72 |
+
encoder_ffn_dim: int = 2048
|
| 73 |
+
encoder_attention_heads: int = 8
|
| 74 |
+
decoder_layers: int = 6
|
| 75 |
+
decoder_ffn_dim: int = 2048
|
| 76 |
+
decoder_attention_heads: int = 8
|
| 77 |
+
encoder_layerdrop: float | int = 0.0
|
| 78 |
+
decoder_layerdrop: float | int = 0.0
|
| 79 |
+
is_encoder_decoder: bool = True
|
| 80 |
+
activation_function: str = "relu"
|
| 81 |
+
d_model: int = 256
|
| 82 |
+
dropout: float | int = 0.1
|
| 83 |
+
attention_dropout: float | int = 0.0
|
| 84 |
+
activation_dropout: float | int = 0.0
|
| 85 |
+
init_std: float = 0.02
|
| 86 |
+
init_xavier_std: float = 1.0
|
| 87 |
+
auxiliary_loss: bool = False
|
| 88 |
+
position_embedding_type: str = "sine"
|
| 89 |
+
dilation: bool = False
|
| 90 |
+
class_cost: int = 1
|
| 91 |
+
bbox_cost: int = 5
|
| 92 |
+
giou_cost: int = 2
|
| 93 |
+
mask_loss_coefficient: int = 1
|
| 94 |
+
dice_loss_coefficient: int = 1
|
| 95 |
+
bbox_loss_coefficient: int = 5
|
| 96 |
+
giou_loss_coefficient: int = 2
|
| 97 |
+
eos_coefficient: float = 0.1
|
| 98 |
+
|
| 99 |
+
def __post_init__(self, **kwargs):
|
| 100 |
+
backbone_kwargs = kwargs.get("backbone_kwargs", {})
|
| 101 |
+
timm_default_kwargs = {
|
| 102 |
+
"num_channels": backbone_kwargs.get("num_channels", self.num_channels),
|
| 103 |
+
"features_only": True,
|
| 104 |
+
"use_pretrained_backbone": False,
|
| 105 |
+
"out_indices": backbone_kwargs.get("out_indices", [1, 2, 3, 4]),
|
| 106 |
+
}
|
| 107 |
+
if self.dilation:
|
| 108 |
+
timm_default_kwargs["output_stride"] = backbone_kwargs.get("output_stride", 16)
|
| 109 |
+
|
| 110 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 111 |
+
backbone_config=self.backbone_config,
|
| 112 |
+
default_backbone="resnet50",
|
| 113 |
+
default_config_type="resnet",
|
| 114 |
+
default_config_kwargs={"out_features": ["stage4"]},
|
| 115 |
+
timm_default_kwargs=timm_default_kwargs,
|
| 116 |
+
**kwargs,
|
| 117 |
+
)
|
| 118 |
+
super().__post_init__(**kwargs)
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
@auto_docstring(checkpoint="facebook/maskformer-swin-base-ade")
|
| 122 |
+
@strict
|
| 123 |
+
class MaskFormerConfig(PreTrainedConfig):
|
| 124 |
+
r"""
|
| 125 |
+
fpn_feature_size (`int`, *optional*, defaults to 256):
|
| 126 |
+
The Feature Pyramid Network's features size.
|
| 127 |
+
mask_feature_size (`int`, *optional*, defaults to 256):
|
| 128 |
+
The masks' features size, this value will also be used to specify the Feature Pyramid Network features'
|
| 129 |
+
size.
|
| 130 |
+
decoder_config (`Dict`, *optional*):
|
| 131 |
+
The configuration passed to the transformer decoder model, if unset the base config for `detr-resnet-50`
|
| 132 |
+
will be used.
|
| 133 |
+
cross_entropy_weight (`float`, *optional*, defaults to 1.0):
|
| 134 |
+
The weight for the cross entropy loss.
|
| 135 |
+
output_auxiliary_logits (`bool`, *optional*):
|
| 136 |
+
Should the model output its `auxiliary_logits` or not.
|
| 137 |
+
|
| 138 |
+
Raises:
|
| 139 |
+
`ValueError`:
|
| 140 |
+
Raised if the backbone model type selected is not in `["swin"]` or the decoder model type selected is not
|
| 141 |
+
in `["detr"]`
|
| 142 |
+
|
| 143 |
+
Examples:
|
| 144 |
+
|
| 145 |
+
```python
|
| 146 |
+
>>> from transformers import MaskFormerConfig, MaskFormerModel
|
| 147 |
+
|
| 148 |
+
>>> # Initializing a MaskFormer facebook/maskformer-swin-base-ade configuration
|
| 149 |
+
>>> configuration = MaskFormerConfig()
|
| 150 |
+
|
| 151 |
+
>>> # Initializing a model (with random weights) from the facebook/maskformer-swin-base-ade style configuration
|
| 152 |
+
>>> model = MaskFormerModel(configuration)
|
| 153 |
+
|
| 154 |
+
>>> # Accessing the model configuration
|
| 155 |
+
>>> configuration = model.config
|
| 156 |
+
```
|
| 157 |
+
|
| 158 |
+
"""
|
| 159 |
+
|
| 160 |
+
model_type = "maskformer"
|
| 161 |
+
sub_configs = {"backbone_config": AutoConfig, "decoder_config": AutoConfig}
|
| 162 |
+
attribute_map = {"hidden_size": "mask_feature_size"}
|
| 163 |
+
backbones_supported = ["resnet", "swin"]
|
| 164 |
+
decoders_supported = ["detr"]
|
| 165 |
+
|
| 166 |
+
fpn_feature_size: int = 256
|
| 167 |
+
mask_feature_size: int = 256
|
| 168 |
+
no_object_weight: float = 0.1
|
| 169 |
+
use_auxiliary_loss: bool = False
|
| 170 |
+
backbone_config: dict | PreTrainedConfig | None = None
|
| 171 |
+
decoder_config: dict | PreTrainedConfig | None = None
|
| 172 |
+
init_std: float = 0.02
|
| 173 |
+
init_xavier_std: float = 1.0
|
| 174 |
+
dice_weight: float = 1.0
|
| 175 |
+
cross_entropy_weight: float = 1.0
|
| 176 |
+
mask_weight: float = 20.0
|
| 177 |
+
output_auxiliary_logits: bool | None = None
|
| 178 |
+
|
| 179 |
+
def __post_init__(self, **kwargs):
|
| 180 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 181 |
+
backbone_config=self.backbone_config,
|
| 182 |
+
default_config_type="swin",
|
| 183 |
+
default_config_kwargs={
|
| 184 |
+
"depths": [2, 2, 18, 2],
|
| 185 |
+
"drop_path_rate": 0.3,
|
| 186 |
+
"image_size": 384,
|
| 187 |
+
"embed_dim": 128,
|
| 188 |
+
"num_heads": [4, 8, 16, 32],
|
| 189 |
+
"window_size": 12,
|
| 190 |
+
"out_features": ["stage1", "stage2", "stage3", "stage4"],
|
| 191 |
+
},
|
| 192 |
+
**kwargs,
|
| 193 |
+
)
|
| 194 |
+
|
| 195 |
+
# verify that the backbone is supported
|
| 196 |
+
if self.backbone_config is not None and self.backbone_config.model_type not in self.backbones_supported:
|
| 197 |
+
logger.warning_once(
|
| 198 |
+
f"Backbone {self.backbone_config.model_type} is not a supported model and may not be compatible with MaskFormer. "
|
| 199 |
+
f"Supported model types: {','.join(self.backbones_supported)}"
|
| 200 |
+
)
|
| 201 |
+
|
| 202 |
+
if self.decoder_config is None:
|
| 203 |
+
# fall back to https://huggingface.co/facebook/detr-resnet-50
|
| 204 |
+
self.decoder_config = MaskFormerDetrConfig()
|
| 205 |
+
else:
|
| 206 |
+
# verify that the decoder is supported
|
| 207 |
+
decoder_type = (
|
| 208 |
+
self.decoder_config.pop("model_type")
|
| 209 |
+
if isinstance(self.decoder_config, dict)
|
| 210 |
+
else self.decoder_config.model_type
|
| 211 |
+
)
|
| 212 |
+
if decoder_type not in self.decoders_supported:
|
| 213 |
+
raise ValueError(
|
| 214 |
+
f"Transformer Decoder {decoder_type} not supported, please use one of"
|
| 215 |
+
f" {','.join(self.decoders_supported)}"
|
| 216 |
+
)
|
| 217 |
+
if isinstance(self.decoder_config, dict):
|
| 218 |
+
config_class = CONFIG_MAPPING[decoder_type]
|
| 219 |
+
self.decoder_config = config_class.from_dict(self.decoder_config)
|
| 220 |
+
|
| 221 |
+
self.num_attention_heads = self.decoder_config.encoder_attention_heads
|
| 222 |
+
self.num_hidden_layers = self.decoder_config.num_hidden_layers
|
| 223 |
+
super().__post_init__(**kwargs)
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
__all__ = ["MaskFormerConfig", "MaskFormerDetrConfig"]
|
third_party/transformers/src/transformers/models/maskformer/configuration_maskformer_swin.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""MaskFormer Swin Transformer model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...backbone_utils import BackboneConfigMixin
|
| 19 |
+
from ...configuration_utils import PreTrainedConfig
|
| 20 |
+
from ...utils import auto_docstring
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
@auto_docstring(checkpoint="microsoft/swin-tiny-patch4-window7-224")
|
| 24 |
+
@strict
|
| 25 |
+
class MaskFormerSwinConfig(BackboneConfigMixin, PreTrainedConfig):
|
| 26 |
+
r"""
|
| 27 |
+
window_size (`int`, *optional*, defaults to 7):
|
| 28 |
+
Size of windows.
|
| 29 |
+
|
| 30 |
+
Example:
|
| 31 |
+
|
| 32 |
+
```python
|
| 33 |
+
>>> from transformers import MaskFormerSwinConfig, MaskFormerSwinModel
|
| 34 |
+
|
| 35 |
+
>>> # Initializing a microsoft/swin-tiny-patch4-window7-224 style configuration
|
| 36 |
+
>>> configuration = MaskFormerSwinConfig()
|
| 37 |
+
|
| 38 |
+
>>> # Initializing a model (with random weights) from the microsoft/swin-tiny-patch4-window7-224 style configuration
|
| 39 |
+
>>> model = MaskFormerSwinModel(configuration)
|
| 40 |
+
|
| 41 |
+
>>> # Accessing the model configuration
|
| 42 |
+
>>> configuration = model.config
|
| 43 |
+
```"""
|
| 44 |
+
|
| 45 |
+
model_type = "maskformer-swin"
|
| 46 |
+
|
| 47 |
+
attribute_map = {
|
| 48 |
+
"num_attention_heads": "num_heads",
|
| 49 |
+
"num_hidden_layers": "num_layers",
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
image_size: int | list[int] | tuple[int, int] = 224
|
| 53 |
+
patch_size: int | list[int] | tuple[int, int] = 4
|
| 54 |
+
num_channels: int = 3
|
| 55 |
+
embed_dim: int = 96
|
| 56 |
+
depths: list[int] | tuple[int, ...] = (2, 2, 6, 2)
|
| 57 |
+
num_heads: list[int] | tuple[int, ...] = (3, 6, 12, 24)
|
| 58 |
+
window_size: int = 7
|
| 59 |
+
mlp_ratio: float = 4.0
|
| 60 |
+
qkv_bias: bool = True
|
| 61 |
+
hidden_dropout_prob: float | int = 0.0
|
| 62 |
+
attention_probs_dropout_prob: float | int = 0.0
|
| 63 |
+
drop_path_rate: float | int = 0.1
|
| 64 |
+
hidden_act: str = "gelu"
|
| 65 |
+
use_absolute_embeddings: bool = False
|
| 66 |
+
initializer_range: float = 0.02
|
| 67 |
+
layer_norm_eps: float = 1e-5
|
| 68 |
+
_out_features: list[str] | None = None
|
| 69 |
+
_out_indices: list[int] | None = None
|
| 70 |
+
|
| 71 |
+
def __post_init__(self, **kwargs):
|
| 72 |
+
# we set the hidden_size attribute in order to make Swin work with VisionEncoderDecoderModel
|
| 73 |
+
# this indicates the channel dimension after the last stage of the model
|
| 74 |
+
self.hidden_size = int(self.embed_dim * 2 ** (len(self.depths) - 1))
|
| 75 |
+
self.stage_names = ["stem"] + [f"stage{idx}" for idx in range(1, len(self.depths) + 1)]
|
| 76 |
+
self.set_output_features_output_indices(
|
| 77 |
+
out_indices=kwargs.pop("out_indices", None), out_features=kwargs.pop("out_features", None)
|
| 78 |
+
)
|
| 79 |
+
super().__post_init__(**kwargs)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
__all__ = ["MaskFormerSwinConfig"]
|
third_party/transformers/src/transformers/models/maskformer/convert_maskformer_original_pytorch_checkpoint_to_pytorch.py
ADDED
|
@@ -0,0 +1,724 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 Meta Platforms, Inc. and The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
import sys
|
| 15 |
+
from argparse import ArgumentParser
|
| 16 |
+
from collections.abc import Iterator
|
| 17 |
+
from dataclasses import dataclass
|
| 18 |
+
from io import BytesIO
|
| 19 |
+
from pathlib import Path
|
| 20 |
+
from pprint import pformat
|
| 21 |
+
from typing import Any
|
| 22 |
+
|
| 23 |
+
import httpx
|
| 24 |
+
import torch
|
| 25 |
+
import torchvision.transforms as T
|
| 26 |
+
from detectron2.checkpoint import DetectionCheckpointer
|
| 27 |
+
from detectron2.config import get_cfg
|
| 28 |
+
from detectron2.data import MetadataCatalog
|
| 29 |
+
from detectron2.projects.deeplab import add_deeplab_config
|
| 30 |
+
from PIL import Image
|
| 31 |
+
from torch import Tensor, nn
|
| 32 |
+
|
| 33 |
+
from transformers.models.maskformer.feature_extraction_maskformer import MaskFormerImageProcessor
|
| 34 |
+
from transformers.models.maskformer.modeling_maskformer import (
|
| 35 |
+
MaskFormerConfig,
|
| 36 |
+
MaskFormerForInstanceSegmentation,
|
| 37 |
+
MaskFormerForInstanceSegmentationOutput,
|
| 38 |
+
MaskFormerModel,
|
| 39 |
+
MaskFormerModelOutput,
|
| 40 |
+
)
|
| 41 |
+
from transformers.utils import logging
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
StateDict = dict[str, Tensor]
|
| 45 |
+
|
| 46 |
+
logging.set_verbosity_info()
|
| 47 |
+
logger = logging.get_logger()
|
| 48 |
+
|
| 49 |
+
torch.manual_seed(0)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
class TrackedStateDict:
|
| 53 |
+
def __init__(self, to_track: dict):
|
| 54 |
+
"""This class "tracks" a python dictionary by keeping track of which item is accessed.
|
| 55 |
+
|
| 56 |
+
Args:
|
| 57 |
+
to_track (Dict): The dictionary we wish to track
|
| 58 |
+
"""
|
| 59 |
+
self.to_track = to_track
|
| 60 |
+
self._seen: set[str] = set()
|
| 61 |
+
|
| 62 |
+
def __getitem__(self, key: str) -> Any:
|
| 63 |
+
return self.to_track[key]
|
| 64 |
+
|
| 65 |
+
def __setitem__(self, key: str, item: Any):
|
| 66 |
+
self._seen.add(key)
|
| 67 |
+
self.to_track[key] = item
|
| 68 |
+
|
| 69 |
+
def diff(self) -> list[str]:
|
| 70 |
+
"""This method returns a set difference between the keys in the tracked state dict and the one we have access so far.
|
| 71 |
+
This is an effective method to check if we have update all the keys
|
| 72 |
+
|
| 73 |
+
Returns:
|
| 74 |
+
list[str]: List of keys not yet updated
|
| 75 |
+
"""
|
| 76 |
+
return set(self.to_track.keys()) - self._seen
|
| 77 |
+
|
| 78 |
+
def copy(self) -> dict:
|
| 79 |
+
# proxy the call to the internal dictionary
|
| 80 |
+
return self.to_track.copy()
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
# We will verify our results on an image of cute cats
|
| 84 |
+
def prepare_img():
|
| 85 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 86 |
+
with httpx.stream("GET", url) as response:
|
| 87 |
+
image = Image.open(BytesIO(response.read()))
|
| 88 |
+
return image
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
@dataclass
|
| 92 |
+
class Args:
|
| 93 |
+
"""Fake command line arguments needed by maskformer/detectron implementation"""
|
| 94 |
+
|
| 95 |
+
config_file: str
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def setup_cfg(args: Args):
|
| 99 |
+
# load config from file and command-line arguments
|
| 100 |
+
cfg = get_cfg()
|
| 101 |
+
add_deeplab_config(cfg)
|
| 102 |
+
add_mask_former_config(cfg)
|
| 103 |
+
cfg.merge_from_file(args.config_file)
|
| 104 |
+
cfg.freeze()
|
| 105 |
+
return cfg
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
class OriginalMaskFormerConfigToOursConverter:
|
| 109 |
+
def __call__(self, original_config: object) -> MaskFormerConfig:
|
| 110 |
+
model = original_config.MODEL
|
| 111 |
+
mask_former = model.MASK_FORMER
|
| 112 |
+
swin = model.SWIN
|
| 113 |
+
|
| 114 |
+
dataset_catalog = MetadataCatalog.get(original_config.DATASETS.TEST[0])
|
| 115 |
+
id2label = dict(enumerate(dataset_catalog.stuff_classes))
|
| 116 |
+
label2id = {label: idx for idx, label in id2label.items()}
|
| 117 |
+
|
| 118 |
+
config: MaskFormerConfig = MaskFormerConfig(
|
| 119 |
+
fpn_feature_size=model.SEM_SEG_HEAD.CONVS_DIM,
|
| 120 |
+
mask_feature_size=model.SEM_SEG_HEAD.MASK_DIM,
|
| 121 |
+
num_labels=model.SEM_SEG_HEAD.NUM_CLASSES,
|
| 122 |
+
no_object_weight=mask_former.NO_OBJECT_WEIGHT,
|
| 123 |
+
num_queries=mask_former.NUM_OBJECT_QUERIES,
|
| 124 |
+
backbone_config={
|
| 125 |
+
"pretrain_img_size": swin.PRETRAIN_IMG_SIZE,
|
| 126 |
+
"image_size": swin.PRETRAIN_IMG_SIZE,
|
| 127 |
+
"in_channels": 3,
|
| 128 |
+
"patch_size": swin.PATCH_SIZE,
|
| 129 |
+
"embed_dim": swin.EMBED_DIM,
|
| 130 |
+
"depths": swin.DEPTHS,
|
| 131 |
+
"num_heads": swin.NUM_HEADS,
|
| 132 |
+
"window_size": swin.WINDOW_SIZE,
|
| 133 |
+
"drop_path_rate": swin.DROP_PATH_RATE,
|
| 134 |
+
"model_type": "swin",
|
| 135 |
+
},
|
| 136 |
+
dice_weight=mask_former.DICE_WEIGHT,
|
| 137 |
+
ce_weight=1.0,
|
| 138 |
+
mask_weight=mask_former.MASK_WEIGHT,
|
| 139 |
+
decoder_config={
|
| 140 |
+
"model_type": "detr",
|
| 141 |
+
"max_position_embeddings": 1024,
|
| 142 |
+
"encoder_layers": 6,
|
| 143 |
+
"encoder_ffn_dim": 2048,
|
| 144 |
+
"encoder_attention_heads": 8,
|
| 145 |
+
"decoder_layers": mask_former.DEC_LAYERS,
|
| 146 |
+
"decoder_ffn_dim": mask_former.DIM_FEEDFORWARD,
|
| 147 |
+
"decoder_attention_heads": mask_former.NHEADS,
|
| 148 |
+
"encoder_layerdrop": 0.0,
|
| 149 |
+
"decoder_layerdrop": 0.0,
|
| 150 |
+
"d_model": mask_former.HIDDEN_DIM,
|
| 151 |
+
"dropout": mask_former.DROPOUT,
|
| 152 |
+
"attention_dropout": 0.0,
|
| 153 |
+
"activation_dropout": 0.0,
|
| 154 |
+
"init_std": 0.02,
|
| 155 |
+
"init_xavier_std": 1.0,
|
| 156 |
+
"scale_embedding": False,
|
| 157 |
+
"auxiliary_loss": False,
|
| 158 |
+
"dilation": False,
|
| 159 |
+
# default pretrained config values
|
| 160 |
+
},
|
| 161 |
+
id2label=id2label,
|
| 162 |
+
label2id=label2id,
|
| 163 |
+
)
|
| 164 |
+
|
| 165 |
+
return config
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
class OriginalMaskFormerConfigToImageProcessorConverter:
|
| 169 |
+
def __call__(self, original_config: object) -> MaskFormerImageProcessor:
|
| 170 |
+
model = original_config.MODEL
|
| 171 |
+
model_input = original_config.INPUT
|
| 172 |
+
dataset_catalog = MetadataCatalog.get(original_config.DATASETS.TEST[0])
|
| 173 |
+
|
| 174 |
+
return MaskFormerImageProcessor(
|
| 175 |
+
image_mean=(torch.tensor(model.PIXEL_MEAN) / 255).tolist(),
|
| 176 |
+
image_std=(torch.tensor(model.PIXEL_STD) / 255).tolist(),
|
| 177 |
+
size=model_input.MIN_SIZE_TEST,
|
| 178 |
+
max_size=model_input.MAX_SIZE_TEST,
|
| 179 |
+
num_labels=model.SEM_SEG_HEAD.NUM_CLASSES,
|
| 180 |
+
ignore_index=dataset_catalog.ignore_label,
|
| 181 |
+
size_divisibility=32, # 32 is required by swin
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
class OriginalMaskFormerCheckpointToOursConverter:
|
| 186 |
+
def __init__(self, original_model: nn.Module, config: MaskFormerConfig):
|
| 187 |
+
self.original_model = original_model
|
| 188 |
+
self.config = config
|
| 189 |
+
|
| 190 |
+
def pop_all(self, renamed_keys: list[tuple[str, str]], dst_state_dict: StateDict, src_state_dict: StateDict):
|
| 191 |
+
for src_key, dst_key in renamed_keys:
|
| 192 |
+
dst_state_dict[dst_key] = src_state_dict.pop(src_key)
|
| 193 |
+
|
| 194 |
+
def replace_backbone(self, dst_state_dict: StateDict, src_state_dict: StateDict, config: MaskFormerConfig):
|
| 195 |
+
dst_prefix: str = "pixel_level_module.encoder"
|
| 196 |
+
src_prefix: str = "backbone"
|
| 197 |
+
|
| 198 |
+
renamed_keys = [
|
| 199 |
+
(
|
| 200 |
+
f"{src_prefix}.patch_embed.proj.weight",
|
| 201 |
+
f"{dst_prefix}.model.embeddings.patch_embeddings.projection.weight",
|
| 202 |
+
),
|
| 203 |
+
(f"{src_prefix}.patch_embed.proj.bias", f"{dst_prefix}.model.embeddings.patch_embeddings.projection.bias"),
|
| 204 |
+
(f"{src_prefix}.patch_embed.norm.weight", f"{dst_prefix}.model.embeddings.norm.weight"),
|
| 205 |
+
(f"{src_prefix}.patch_embed.norm.bias", f"{dst_prefix}.model.embeddings.norm.bias"),
|
| 206 |
+
]
|
| 207 |
+
num_layers = len(config.backbone_config.depths)
|
| 208 |
+
for layer_idx in range(num_layers):
|
| 209 |
+
for block_idx in range(config.backbone_config.depths[layer_idx]):
|
| 210 |
+
renamed_keys.extend(
|
| 211 |
+
[ # src, dst
|
| 212 |
+
(
|
| 213 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.norm1.weight",
|
| 214 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.layernorm_before.weight",
|
| 215 |
+
),
|
| 216 |
+
(
|
| 217 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.norm1.bias",
|
| 218 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.layernorm_before.bias",
|
| 219 |
+
),
|
| 220 |
+
(
|
| 221 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.attn.relative_position_bias_table",
|
| 222 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.self.relative_position_bias_table",
|
| 223 |
+
),
|
| 224 |
+
]
|
| 225 |
+
)
|
| 226 |
+
# now we need to handle the attentions
|
| 227 |
+
# read in weights + bias of input projection layer of cross-attention
|
| 228 |
+
|
| 229 |
+
src_att_weight = src_state_dict[f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.attn.qkv.weight"]
|
| 230 |
+
src_att_bias = src_state_dict[f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.attn.qkv.bias"]
|
| 231 |
+
|
| 232 |
+
size = src_att_weight.shape[0]
|
| 233 |
+
offset = size // 3
|
| 234 |
+
dst_state_dict[
|
| 235 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.self.query.weight"
|
| 236 |
+
] = src_att_weight[:offset, :]
|
| 237 |
+
dst_state_dict[
|
| 238 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.self.query.bias"
|
| 239 |
+
] = src_att_bias[:offset]
|
| 240 |
+
|
| 241 |
+
dst_state_dict[
|
| 242 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.self.key.weight"
|
| 243 |
+
] = src_att_weight[offset : offset * 2, :]
|
| 244 |
+
dst_state_dict[
|
| 245 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.self.key.bias"
|
| 246 |
+
] = src_att_bias[offset : offset * 2]
|
| 247 |
+
|
| 248 |
+
dst_state_dict[
|
| 249 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.self.value.weight"
|
| 250 |
+
] = src_att_weight[-offset:, :]
|
| 251 |
+
dst_state_dict[
|
| 252 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.self.value.bias"
|
| 253 |
+
] = src_att_bias[-offset:]
|
| 254 |
+
|
| 255 |
+
# let's pop them
|
| 256 |
+
src_state_dict.pop(f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.attn.qkv.weight")
|
| 257 |
+
src_state_dict.pop(f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.attn.qkv.bias")
|
| 258 |
+
# proj
|
| 259 |
+
renamed_keys.extend(
|
| 260 |
+
[
|
| 261 |
+
(
|
| 262 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.attn.proj.weight",
|
| 263 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.output.dense.weight",
|
| 264 |
+
),
|
| 265 |
+
(
|
| 266 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.attn.proj.bias",
|
| 267 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.output.dense.bias",
|
| 268 |
+
),
|
| 269 |
+
]
|
| 270 |
+
)
|
| 271 |
+
|
| 272 |
+
# second norm
|
| 273 |
+
renamed_keys.extend(
|
| 274 |
+
[
|
| 275 |
+
(
|
| 276 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.norm2.weight",
|
| 277 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.layernorm_after.weight",
|
| 278 |
+
),
|
| 279 |
+
(
|
| 280 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.norm2.bias",
|
| 281 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.layernorm_after.bias",
|
| 282 |
+
),
|
| 283 |
+
]
|
| 284 |
+
)
|
| 285 |
+
|
| 286 |
+
# mlp
|
| 287 |
+
renamed_keys.extend(
|
| 288 |
+
[
|
| 289 |
+
(
|
| 290 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.mlp.fc1.weight",
|
| 291 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.intermediate.dense.weight",
|
| 292 |
+
),
|
| 293 |
+
(
|
| 294 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.mlp.fc1.bias",
|
| 295 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.intermediate.dense.bias",
|
| 296 |
+
),
|
| 297 |
+
(
|
| 298 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.mlp.fc2.weight",
|
| 299 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.output.dense.weight",
|
| 300 |
+
),
|
| 301 |
+
(
|
| 302 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.mlp.fc2.bias",
|
| 303 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.output.dense.bias",
|
| 304 |
+
),
|
| 305 |
+
]
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
renamed_keys.extend(
|
| 309 |
+
[
|
| 310 |
+
(
|
| 311 |
+
f"{src_prefix}.layers.{layer_idx}.blocks.{block_idx}.attn.relative_position_index",
|
| 312 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.blocks.{block_idx}.attention.self.relative_position_index",
|
| 313 |
+
)
|
| 314 |
+
]
|
| 315 |
+
)
|
| 316 |
+
|
| 317 |
+
if layer_idx < num_layers - 1:
|
| 318 |
+
# patch merging
|
| 319 |
+
renamed_keys.extend(
|
| 320 |
+
[
|
| 321 |
+
(
|
| 322 |
+
f"{src_prefix}.layers.{layer_idx}.downsample.reduction.weight",
|
| 323 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.downsample.reduction.weight",
|
| 324 |
+
),
|
| 325 |
+
(
|
| 326 |
+
f"{src_prefix}.layers.{layer_idx}.downsample.norm.weight",
|
| 327 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.downsample.norm.weight",
|
| 328 |
+
),
|
| 329 |
+
(
|
| 330 |
+
f"{src_prefix}.layers.{layer_idx}.downsample.norm.bias",
|
| 331 |
+
f"{dst_prefix}.model.encoder.layers.{layer_idx}.downsample.norm.bias",
|
| 332 |
+
),
|
| 333 |
+
]
|
| 334 |
+
)
|
| 335 |
+
|
| 336 |
+
# hidden states norms
|
| 337 |
+
renamed_keys.extend(
|
| 338 |
+
[
|
| 339 |
+
(
|
| 340 |
+
f"{src_prefix}.norm{layer_idx}.weight",
|
| 341 |
+
f"{dst_prefix}.hidden_states_norms.{layer_idx}.weight",
|
| 342 |
+
),
|
| 343 |
+
(
|
| 344 |
+
f"{src_prefix}.norm{layer_idx}.bias",
|
| 345 |
+
f"{dst_prefix}.hidden_states_norms.{layer_idx}.bias",
|
| 346 |
+
),
|
| 347 |
+
]
|
| 348 |
+
)
|
| 349 |
+
self.pop_all(renamed_keys, dst_state_dict, src_state_dict)
|
| 350 |
+
|
| 351 |
+
def replace_pixel_module(self, dst_state_dict: StateDict, src_state_dict: StateDict):
|
| 352 |
+
dst_prefix: str = "pixel_level_module.decoder"
|
| 353 |
+
src_prefix: str = "sem_seg_head.pixel_decoder"
|
| 354 |
+
|
| 355 |
+
self.replace_backbone(dst_state_dict, src_state_dict, self.config)
|
| 356 |
+
|
| 357 |
+
def rename_keys_for_conv(detectron_conv: str, mine_conv: str):
|
| 358 |
+
return [
|
| 359 |
+
(f"{detectron_conv}.weight", f"{mine_conv}.0.weight"),
|
| 360 |
+
# 2 cuz the have act in the middle -> rename it
|
| 361 |
+
(f"{detectron_conv}.norm.weight", f"{mine_conv}.1.weight"),
|
| 362 |
+
(f"{detectron_conv}.norm.bias", f"{mine_conv}.1.bias"),
|
| 363 |
+
]
|
| 364 |
+
|
| 365 |
+
renamed_keys = [
|
| 366 |
+
(f"{src_prefix}.mask_features.weight", f"{dst_prefix}.mask_projection.weight"),
|
| 367 |
+
(f"{src_prefix}.mask_features.bias", f"{dst_prefix}.mask_projection.bias"),
|
| 368 |
+
# the layers in the original one are in reverse order, stem is the last one!
|
| 369 |
+
]
|
| 370 |
+
|
| 371 |
+
renamed_keys.extend(rename_keys_for_conv(f"{src_prefix}.layer_4", f"{dst_prefix}.fpn.stem"))
|
| 372 |
+
|
| 373 |
+
# add all the fpn layers (here we need some config parameters to know the size in advance)
|
| 374 |
+
for src_i, dst_i in zip(range(3, 0, -1), range(0, 3)):
|
| 375 |
+
renamed_keys.extend(
|
| 376 |
+
rename_keys_for_conv(f"{src_prefix}.adapter_{src_i}", f"{dst_prefix}.fpn.layers.{dst_i}.proj")
|
| 377 |
+
)
|
| 378 |
+
renamed_keys.extend(
|
| 379 |
+
rename_keys_for_conv(f"{src_prefix}.layer_{src_i}", f"{dst_prefix}.fpn.layers.{dst_i}.block")
|
| 380 |
+
)
|
| 381 |
+
|
| 382 |
+
self.pop_all(renamed_keys, dst_state_dict, src_state_dict)
|
| 383 |
+
|
| 384 |
+
def rename_keys_in_detr_decoder(self, dst_state_dict: StateDict, src_state_dict: StateDict):
|
| 385 |
+
dst_prefix: str = "transformer_module.decoder"
|
| 386 |
+
src_prefix: str = "sem_seg_head.predictor.transformer.decoder"
|
| 387 |
+
# not sure why we are not popping direcetly here!
|
| 388 |
+
# here we list all keys to be renamed (original name on the left, our name on the right)
|
| 389 |
+
rename_keys = []
|
| 390 |
+
for i in range(self.config.decoder_config.decoder_layers):
|
| 391 |
+
# decoder layers: 2 times output projection, 2 feedforward neural networks and 3 layernorms
|
| 392 |
+
rename_keys.append(
|
| 393 |
+
(
|
| 394 |
+
f"{src_prefix}.layers.{i}.self_attn.out_proj.weight",
|
| 395 |
+
f"{dst_prefix}.layers.{i}.self_attn.out_proj.weight",
|
| 396 |
+
)
|
| 397 |
+
)
|
| 398 |
+
rename_keys.append(
|
| 399 |
+
(
|
| 400 |
+
f"{src_prefix}.layers.{i}.self_attn.out_proj.bias",
|
| 401 |
+
f"{dst_prefix}.layers.{i}.self_attn.out_proj.bias",
|
| 402 |
+
)
|
| 403 |
+
)
|
| 404 |
+
rename_keys.append(
|
| 405 |
+
(
|
| 406 |
+
f"{src_prefix}.layers.{i}.multihead_attn.out_proj.weight",
|
| 407 |
+
f"{dst_prefix}.layers.{i}.encoder_attn.out_proj.weight",
|
| 408 |
+
)
|
| 409 |
+
)
|
| 410 |
+
rename_keys.append(
|
| 411 |
+
(
|
| 412 |
+
f"{src_prefix}.layers.{i}.multihead_attn.out_proj.bias",
|
| 413 |
+
f"{dst_prefix}.layers.{i}.encoder_attn.out_proj.bias",
|
| 414 |
+
)
|
| 415 |
+
)
|
| 416 |
+
rename_keys.append((f"{src_prefix}.layers.{i}.linear1.weight", f"{dst_prefix}.layers.{i}.fc1.weight"))
|
| 417 |
+
rename_keys.append((f"{src_prefix}.layers.{i}.linear1.bias", f"{dst_prefix}.layers.{i}.fc1.bias"))
|
| 418 |
+
rename_keys.append((f"{src_prefix}.layers.{i}.linear2.weight", f"{dst_prefix}.layers.{i}.fc2.weight"))
|
| 419 |
+
rename_keys.append((f"{src_prefix}.layers.{i}.linear2.bias", f"{dst_prefix}.layers.{i}.fc2.bias"))
|
| 420 |
+
rename_keys.append(
|
| 421 |
+
(f"{src_prefix}.layers.{i}.norm1.weight", f"{dst_prefix}.layers.{i}.self_attn_layer_norm.weight")
|
| 422 |
+
)
|
| 423 |
+
rename_keys.append(
|
| 424 |
+
(f"{src_prefix}.layers.{i}.norm1.bias", f"{dst_prefix}.layers.{i}.self_attn_layer_norm.bias")
|
| 425 |
+
)
|
| 426 |
+
rename_keys.append(
|
| 427 |
+
(f"{src_prefix}.layers.{i}.norm2.weight", f"{dst_prefix}.layers.{i}.encoder_attn_layer_norm.weight")
|
| 428 |
+
)
|
| 429 |
+
rename_keys.append(
|
| 430 |
+
(f"{src_prefix}.layers.{i}.norm2.bias", f"{dst_prefix}.layers.{i}.encoder_attn_layer_norm.bias")
|
| 431 |
+
)
|
| 432 |
+
rename_keys.append(
|
| 433 |
+
(f"{src_prefix}.layers.{i}.norm3.weight", f"{dst_prefix}.layers.{i}.final_layer_norm.weight")
|
| 434 |
+
)
|
| 435 |
+
rename_keys.append(
|
| 436 |
+
(f"{src_prefix}.layers.{i}.norm3.bias", f"{dst_prefix}.layers.{i}.final_layer_norm.bias")
|
| 437 |
+
)
|
| 438 |
+
|
| 439 |
+
return rename_keys
|
| 440 |
+
|
| 441 |
+
def replace_q_k_v_in_detr_decoder(self, dst_state_dict: StateDict, src_state_dict: StateDict):
|
| 442 |
+
dst_prefix: str = "transformer_module.decoder"
|
| 443 |
+
src_prefix: str = "sem_seg_head.predictor.transformer.decoder"
|
| 444 |
+
for i in range(self.config.decoder_config.decoder_layers):
|
| 445 |
+
# read in weights + bias of input projection layer of self-attention
|
| 446 |
+
in_proj_weight = src_state_dict.pop(f"{src_prefix}.layers.{i}.self_attn.in_proj_weight")
|
| 447 |
+
in_proj_bias = src_state_dict.pop(f"{src_prefix}.layers.{i}.self_attn.in_proj_bias")
|
| 448 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 449 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.self_attn.q_proj.weight"] = in_proj_weight[:256, :]
|
| 450 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.self_attn.q_proj.bias"] = in_proj_bias[:256]
|
| 451 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.self_attn.k_proj.weight"] = in_proj_weight[256:512, :]
|
| 452 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.self_attn.k_proj.bias"] = in_proj_bias[256:512]
|
| 453 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.self_attn.v_proj.weight"] = in_proj_weight[-256:, :]
|
| 454 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.self_attn.v_proj.bias"] = in_proj_bias[-256:]
|
| 455 |
+
# read in weights + bias of input projection layer of cross-attention
|
| 456 |
+
in_proj_weight_cross_attn = src_state_dict.pop(f"{src_prefix}.layers.{i}.multihead_attn.in_proj_weight")
|
| 457 |
+
in_proj_bias_cross_attn = src_state_dict.pop(f"{src_prefix}.layers.{i}.multihead_attn.in_proj_bias")
|
| 458 |
+
# next, add query, keys and values (in that order) of cross-attention to the state dict
|
| 459 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.encoder_attn.q_proj.weight"] = in_proj_weight_cross_attn[:256, :]
|
| 460 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.encoder_attn.q_proj.bias"] = in_proj_bias_cross_attn[:256]
|
| 461 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.encoder_attn.k_proj.weight"] = in_proj_weight_cross_attn[
|
| 462 |
+
256:512, :
|
| 463 |
+
]
|
| 464 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.encoder_attn.k_proj.bias"] = in_proj_bias_cross_attn[256:512]
|
| 465 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.encoder_attn.v_proj.weight"] = in_proj_weight_cross_attn[-256:, :]
|
| 466 |
+
dst_state_dict[f"{dst_prefix}.layers.{i}.encoder_attn.v_proj.bias"] = in_proj_bias_cross_attn[-256:]
|
| 467 |
+
|
| 468 |
+
def replace_detr_decoder(self, dst_state_dict: StateDict, src_state_dict: StateDict):
|
| 469 |
+
dst_prefix: str = "transformer_module.decoder"
|
| 470 |
+
src_prefix: str = "sem_seg_head.predictor.transformer.decoder"
|
| 471 |
+
renamed_keys = self.rename_keys_in_detr_decoder(dst_state_dict, src_state_dict)
|
| 472 |
+
# add more
|
| 473 |
+
renamed_keys.extend(
|
| 474 |
+
[
|
| 475 |
+
(f"{src_prefix}.norm.weight", f"{dst_prefix}.layernorm.weight"),
|
| 476 |
+
(f"{src_prefix}.norm.bias", f"{dst_prefix}.layernorm.bias"),
|
| 477 |
+
]
|
| 478 |
+
)
|
| 479 |
+
|
| 480 |
+
self.pop_all(renamed_keys, dst_state_dict, src_state_dict)
|
| 481 |
+
|
| 482 |
+
self.replace_q_k_v_in_detr_decoder(dst_state_dict, src_state_dict)
|
| 483 |
+
|
| 484 |
+
def replace_transformer_module(self, dst_state_dict: StateDict, src_state_dict: StateDict):
|
| 485 |
+
dst_prefix: str = "transformer_module"
|
| 486 |
+
src_prefix: str = "sem_seg_head.predictor"
|
| 487 |
+
|
| 488 |
+
self.replace_detr_decoder(dst_state_dict, src_state_dict)
|
| 489 |
+
|
| 490 |
+
renamed_keys = [
|
| 491 |
+
(f"{src_prefix}.query_embed.weight", f"{dst_prefix}.queries_embedder.weight"),
|
| 492 |
+
(f"{src_prefix}.input_proj.weight", f"{dst_prefix}.input_projection.weight"),
|
| 493 |
+
(f"{src_prefix}.input_proj.bias", f"{dst_prefix}.input_projection.bias"),
|
| 494 |
+
]
|
| 495 |
+
|
| 496 |
+
self.pop_all(renamed_keys, dst_state_dict, src_state_dict)
|
| 497 |
+
|
| 498 |
+
def replace_instance_segmentation_module(self, dst_state_dict: StateDict, src_state_dict: StateDict):
|
| 499 |
+
# NOTE in our case we don't have a prefix, thus we removed the "." from the keys later on!
|
| 500 |
+
dst_prefix: str = ""
|
| 501 |
+
src_prefix: str = "sem_seg_head.predictor"
|
| 502 |
+
|
| 503 |
+
renamed_keys = [
|
| 504 |
+
(f"{src_prefix}.class_embed.weight", f"{dst_prefix}class_predictor.weight"),
|
| 505 |
+
(f"{src_prefix}.class_embed.bias", f"{dst_prefix}class_predictor.bias"),
|
| 506 |
+
]
|
| 507 |
+
|
| 508 |
+
mlp_len = 3
|
| 509 |
+
for i in range(mlp_len):
|
| 510 |
+
renamed_keys.extend(
|
| 511 |
+
[
|
| 512 |
+
(f"{src_prefix}.mask_embed.layers.{i}.weight", f"{dst_prefix}mask_embedder.{i}.0.weight"),
|
| 513 |
+
(f"{src_prefix}.mask_embed.layers.{i}.bias", f"{dst_prefix}mask_embedder.{i}.0.bias"),
|
| 514 |
+
]
|
| 515 |
+
)
|
| 516 |
+
logger.info(f"Replacing keys {pformat(renamed_keys)}")
|
| 517 |
+
self.pop_all(renamed_keys, dst_state_dict, src_state_dict)
|
| 518 |
+
|
| 519 |
+
def convert(self, mask_former: MaskFormerModel) -> MaskFormerModel:
|
| 520 |
+
dst_state_dict = TrackedStateDict(mask_former.state_dict())
|
| 521 |
+
src_state_dict = self.original_model.state_dict()
|
| 522 |
+
|
| 523 |
+
self.replace_pixel_module(dst_state_dict, src_state_dict)
|
| 524 |
+
self.replace_transformer_module(dst_state_dict, src_state_dict)
|
| 525 |
+
|
| 526 |
+
logger.info(f"Missed keys are {pformat(dst_state_dict.diff())}")
|
| 527 |
+
logger.info(f"Not copied keys are {pformat(src_state_dict.keys())}")
|
| 528 |
+
logger.info("🙌 Done")
|
| 529 |
+
|
| 530 |
+
mask_former.load_state_dict(dst_state_dict)
|
| 531 |
+
|
| 532 |
+
return mask_former
|
| 533 |
+
|
| 534 |
+
def convert_instance_segmentation(
|
| 535 |
+
self, mask_former: MaskFormerForInstanceSegmentation
|
| 536 |
+
) -> MaskFormerForInstanceSegmentation:
|
| 537 |
+
dst_state_dict = TrackedStateDict(mask_former.state_dict())
|
| 538 |
+
src_state_dict = self.original_model.state_dict()
|
| 539 |
+
|
| 540 |
+
self.replace_instance_segmentation_module(dst_state_dict, src_state_dict)
|
| 541 |
+
|
| 542 |
+
mask_former.load_state_dict(dst_state_dict)
|
| 543 |
+
|
| 544 |
+
return mask_former
|
| 545 |
+
|
| 546 |
+
@staticmethod
|
| 547 |
+
def using_dirs(checkpoints_dir: Path, config_dir: Path) -> Iterator[tuple[object, Path, Path]]:
|
| 548 |
+
checkpoints: list[Path] = checkpoints_dir.glob("**/*.pkl")
|
| 549 |
+
|
| 550 |
+
for checkpoint in checkpoints:
|
| 551 |
+
logger.info(f"Converting {checkpoint.stem}")
|
| 552 |
+
# find associated config file
|
| 553 |
+
config: Path = config_dir / checkpoint.parents[0].stem / "swin" / f"{checkpoint.stem}.yaml"
|
| 554 |
+
|
| 555 |
+
yield config, checkpoint
|
| 556 |
+
|
| 557 |
+
|
| 558 |
+
def test(original_model, our_model: MaskFormerForInstanceSegmentation, image_processor: MaskFormerImageProcessor):
|
| 559 |
+
with torch.no_grad():
|
| 560 |
+
original_model = original_model.eval()
|
| 561 |
+
our_model = our_model.eval()
|
| 562 |
+
|
| 563 |
+
im = prepare_img()
|
| 564 |
+
|
| 565 |
+
tr = T.Compose(
|
| 566 |
+
[
|
| 567 |
+
T.Resize((384, 384)),
|
| 568 |
+
T.ToTensor(),
|
| 569 |
+
T.Normalize(
|
| 570 |
+
mean=torch.tensor([123.675, 116.280, 103.530]) / 255.0,
|
| 571 |
+
std=torch.tensor([58.395, 57.120, 57.375]) / 255.0,
|
| 572 |
+
),
|
| 573 |
+
],
|
| 574 |
+
)
|
| 575 |
+
|
| 576 |
+
x = tr(im).unsqueeze(0)
|
| 577 |
+
|
| 578 |
+
original_model_backbone_features = original_model.backbone(x.clone())
|
| 579 |
+
|
| 580 |
+
our_model_output: MaskFormerModelOutput = our_model.model(x.clone(), output_hidden_states=True)
|
| 581 |
+
|
| 582 |
+
for original_model_feature, our_model_feature in zip(
|
| 583 |
+
original_model_backbone_features.values(), our_model_output.encoder_hidden_states
|
| 584 |
+
):
|
| 585 |
+
assert torch.allclose(original_model_feature, our_model_feature, atol=1e-3), (
|
| 586 |
+
"The backbone features are not the same."
|
| 587 |
+
)
|
| 588 |
+
|
| 589 |
+
original_model_pixel_out = original_model.sem_seg_head.pixel_decoder.forward_features(
|
| 590 |
+
original_model_backbone_features
|
| 591 |
+
)
|
| 592 |
+
|
| 593 |
+
assert torch.allclose(
|
| 594 |
+
original_model_pixel_out[0], our_model_output.pixel_decoder_last_hidden_state, atol=1e-4
|
| 595 |
+
), "The pixel decoder feature are not the same"
|
| 596 |
+
|
| 597 |
+
# let's test the full model
|
| 598 |
+
original_model_out = original_model([{"image": x.squeeze(0)}])
|
| 599 |
+
|
| 600 |
+
original_segmentation = original_model_out[0]["sem_seg"]
|
| 601 |
+
|
| 602 |
+
our_model_out: MaskFormerForInstanceSegmentationOutput = our_model(x)
|
| 603 |
+
|
| 604 |
+
our_segmentation = image_processor.post_process_segmentation(our_model_out, target_size=(384, 384))
|
| 605 |
+
|
| 606 |
+
assert torch.allclose(original_segmentation, our_segmentation, atol=1e-3), (
|
| 607 |
+
"The segmentation image is not the same."
|
| 608 |
+
)
|
| 609 |
+
|
| 610 |
+
logger.info("Test passed!")
|
| 611 |
+
|
| 612 |
+
|
| 613 |
+
def get_name(checkpoint_file: Path):
|
| 614 |
+
model_name_raw: str = checkpoint_file.stem
|
| 615 |
+
# model_name_raw is something like maskformer_panoptic_swin_base_IN21k_384_bs64_554k
|
| 616 |
+
parent_name: str = checkpoint_file.parents[0].stem
|
| 617 |
+
backbone = "swin"
|
| 618 |
+
dataset = ""
|
| 619 |
+
if "coco" in parent_name:
|
| 620 |
+
dataset = "coco"
|
| 621 |
+
elif "ade" in parent_name:
|
| 622 |
+
dataset = "ade"
|
| 623 |
+
else:
|
| 624 |
+
raise ValueError(f"{parent_name} must be wrong since we didn't find 'coco' or 'ade' in it ")
|
| 625 |
+
|
| 626 |
+
backbone_types = ["tiny", "small", "base", "large"]
|
| 627 |
+
|
| 628 |
+
backbone_type = list(filter(lambda x: x in model_name_raw, backbone_types))[0]
|
| 629 |
+
|
| 630 |
+
model_name = f"maskformer-{backbone}-{backbone_type}-{dataset}"
|
| 631 |
+
|
| 632 |
+
return model_name
|
| 633 |
+
|
| 634 |
+
|
| 635 |
+
if __name__ == "__main__":
|
| 636 |
+
parser = ArgumentParser(
|
| 637 |
+
description="Command line to convert the original maskformers (with swin backbone) to our implementations."
|
| 638 |
+
)
|
| 639 |
+
|
| 640 |
+
parser.add_argument(
|
| 641 |
+
"--checkpoints_dir",
|
| 642 |
+
type=Path,
|
| 643 |
+
help=(
|
| 644 |
+
"A directory containing the model's checkpoints. The directory has to have the following structure:"
|
| 645 |
+
" <DIR_NAME>/<DATASET_NAME>/<CONFIG_NAME>.pkl\n"
|
| 646 |
+
"Given the files are in the pickle format, please be wary of passing it files you trust."
|
| 647 |
+
),
|
| 648 |
+
)
|
| 649 |
+
parser.add_argument(
|
| 650 |
+
"--configs_dir",
|
| 651 |
+
type=Path,
|
| 652 |
+
help=(
|
| 653 |
+
"A directory containing the model's configs, see detectron2 doc. The directory has to have the following"
|
| 654 |
+
" structure: <DIR_NAME>/<DATASET_NAME>/<CONFIG_NAME>.yaml"
|
| 655 |
+
),
|
| 656 |
+
)
|
| 657 |
+
parser.add_argument(
|
| 658 |
+
"--pytorch_dump_folder_path",
|
| 659 |
+
required=True,
|
| 660 |
+
type=Path,
|
| 661 |
+
help="Path to the folder to output PyTorch models.",
|
| 662 |
+
)
|
| 663 |
+
parser.add_argument(
|
| 664 |
+
"--maskformer_dir",
|
| 665 |
+
required=True,
|
| 666 |
+
type=Path,
|
| 667 |
+
help=(
|
| 668 |
+
"A path to MaskFormer's original implementation directory. You can download from here:"
|
| 669 |
+
" https://github.com/facebookresearch/MaskFormer"
|
| 670 |
+
),
|
| 671 |
+
)
|
| 672 |
+
|
| 673 |
+
args = parser.parse_args()
|
| 674 |
+
|
| 675 |
+
checkpoints_dir: Path = args.checkpoints_dir
|
| 676 |
+
config_dir: Path = args.configs_dir
|
| 677 |
+
save_directory: Path = args.pytorch_dump_folder_path
|
| 678 |
+
maskformer_dir: Path = args.maskformer_dir
|
| 679 |
+
# append the path to the parents to maskformer dir
|
| 680 |
+
sys.path.append(str(maskformer_dir.parent))
|
| 681 |
+
# and import what's needed
|
| 682 |
+
from MaskFormer.mask_former import add_mask_former_config
|
| 683 |
+
from MaskFormer.mask_former.mask_former_model import MaskFormer as OriginalMaskFormer
|
| 684 |
+
|
| 685 |
+
if not save_directory.exists():
|
| 686 |
+
save_directory.mkdir(parents=True)
|
| 687 |
+
|
| 688 |
+
for config_file, checkpoint_file in OriginalMaskFormerCheckpointToOursConverter.using_dirs(
|
| 689 |
+
checkpoints_dir, config_dir
|
| 690 |
+
):
|
| 691 |
+
image_processor = OriginalMaskFormerConfigToImageProcessorConverter()(setup_cfg(Args(config_file=config_file)))
|
| 692 |
+
|
| 693 |
+
original_config = setup_cfg(Args(config_file=config_file))
|
| 694 |
+
mask_former_kwargs = OriginalMaskFormer.from_config(original_config)
|
| 695 |
+
|
| 696 |
+
original_model = OriginalMaskFormer(**mask_former_kwargs).eval()
|
| 697 |
+
|
| 698 |
+
DetectionCheckpointer(original_model).load(str(checkpoint_file))
|
| 699 |
+
|
| 700 |
+
config: MaskFormerConfig = OriginalMaskFormerConfigToOursConverter()(original_config)
|
| 701 |
+
|
| 702 |
+
mask_former = MaskFormerModel(config=config).eval()
|
| 703 |
+
|
| 704 |
+
converter = OriginalMaskFormerCheckpointToOursConverter(original_model, config)
|
| 705 |
+
|
| 706 |
+
maskformer = converter.convert(mask_former)
|
| 707 |
+
|
| 708 |
+
mask_former_for_instance_segmentation = MaskFormerForInstanceSegmentation(config=config).eval()
|
| 709 |
+
|
| 710 |
+
mask_former_for_instance_segmentation.model = mask_former
|
| 711 |
+
mask_former_for_instance_segmentation = converter.convert_instance_segmentation(
|
| 712 |
+
mask_former_for_instance_segmentation
|
| 713 |
+
)
|
| 714 |
+
|
| 715 |
+
test(original_model, mask_former_for_instance_segmentation, image_processor)
|
| 716 |
+
|
| 717 |
+
model_name = get_name(checkpoint_file)
|
| 718 |
+
logger.info(f"Saving {model_name}")
|
| 719 |
+
|
| 720 |
+
image_processor.save_pretrained(save_directory / model_name)
|
| 721 |
+
mask_former_for_instance_segmentation.save_pretrained(save_directory / model_name)
|
| 722 |
+
|
| 723 |
+
image_processor.push_to_hub(repo_id=model_name)
|
| 724 |
+
mask_former_for_instance_segmentation.push_to_hub(repo_id=model_name)
|
third_party/transformers/src/transformers/models/maskformer/convert_maskformer_resnet_to_pytorch.py
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert MaskFormer checkpoints with ResNet backbone from the original repository. URL:
|
| 15 |
+
https://github.com/facebookresearch/MaskFormer"""
|
| 16 |
+
|
| 17 |
+
import argparse
|
| 18 |
+
import json
|
| 19 |
+
import os
|
| 20 |
+
import pickle
|
| 21 |
+
from io import BytesIO
|
| 22 |
+
from pathlib import Path
|
| 23 |
+
|
| 24 |
+
import httpx
|
| 25 |
+
import torch
|
| 26 |
+
from huggingface_hub import hf_hub_download
|
| 27 |
+
from PIL import Image
|
| 28 |
+
|
| 29 |
+
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation, MaskFormerImageProcessor, ResNetConfig
|
| 30 |
+
from transformers.utils import logging
|
| 31 |
+
|
| 32 |
+
from ...utils import strtobool
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
logging.set_verbosity_info()
|
| 36 |
+
logger = logging.get_logger(__name__)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def get_maskformer_config(model_name: str):
|
| 40 |
+
if "resnet101c" in model_name:
|
| 41 |
+
# TODO add support for ResNet-C backbone, which uses a "deeplab" stem
|
| 42 |
+
raise NotImplementedError("To do")
|
| 43 |
+
elif "resnet101" in model_name:
|
| 44 |
+
backbone_config = ResNetConfig.from_pretrained(
|
| 45 |
+
"microsoft/resnet-101", out_features=["stage1", "stage2", "stage3", "stage4"]
|
| 46 |
+
)
|
| 47 |
+
else:
|
| 48 |
+
backbone_config = ResNetConfig.from_pretrained(
|
| 49 |
+
"microsoft/resnet-50", out_features=["stage1", "stage2", "stage3", "stage4"]
|
| 50 |
+
)
|
| 51 |
+
config = MaskFormerConfig(backbone_config=backbone_config)
|
| 52 |
+
|
| 53 |
+
repo_id = "huggingface/label-files"
|
| 54 |
+
if "ade20k-full" in model_name:
|
| 55 |
+
config.num_labels = 847
|
| 56 |
+
filename = "maskformer-ade20k-full-id2label.json"
|
| 57 |
+
elif "ade" in model_name:
|
| 58 |
+
config.num_labels = 150
|
| 59 |
+
filename = "ade20k-id2label.json"
|
| 60 |
+
elif "coco-stuff" in model_name:
|
| 61 |
+
config.num_labels = 171
|
| 62 |
+
filename = "maskformer-coco-stuff-id2label.json"
|
| 63 |
+
elif "coco" in model_name:
|
| 64 |
+
# TODO
|
| 65 |
+
config.num_labels = 133
|
| 66 |
+
filename = "coco-panoptic-id2label.json"
|
| 67 |
+
elif "cityscapes" in model_name:
|
| 68 |
+
config.num_labels = 19
|
| 69 |
+
filename = "cityscapes-id2label.json"
|
| 70 |
+
elif "vistas" in model_name:
|
| 71 |
+
config.num_labels = 65
|
| 72 |
+
filename = "mapillary-vistas-id2label.json"
|
| 73 |
+
|
| 74 |
+
id2label = json.load(open(hf_hub_download(repo_id, filename, repo_type="dataset"), "r"))
|
| 75 |
+
id2label = {int(k): v for k, v in id2label.items()}
|
| 76 |
+
config.id2label = id2label
|
| 77 |
+
config.label2id = {v: k for k, v in id2label.items()}
|
| 78 |
+
|
| 79 |
+
return config
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def create_rename_keys(config):
|
| 83 |
+
rename_keys = []
|
| 84 |
+
# stem
|
| 85 |
+
# fmt: off
|
| 86 |
+
rename_keys.append(("backbone.stem.conv1.weight", "model.pixel_level_module.encoder.embedder.embedder.convolution.weight"))
|
| 87 |
+
rename_keys.append(("backbone.stem.conv1.norm.weight", "model.pixel_level_module.encoder.embedder.embedder.normalization.weight"))
|
| 88 |
+
rename_keys.append(("backbone.stem.conv1.norm.bias", "model.pixel_level_module.encoder.embedder.embedder.normalization.bias"))
|
| 89 |
+
rename_keys.append(("backbone.stem.conv1.norm.running_mean", "model.pixel_level_module.encoder.embedder.embedder.normalization.running_mean"))
|
| 90 |
+
rename_keys.append(("backbone.stem.conv1.norm.running_var", "model.pixel_level_module.encoder.embedder.embedder.normalization.running_var"))
|
| 91 |
+
# fmt: on
|
| 92 |
+
# stages
|
| 93 |
+
for stage_idx in range(len(config.backbone_config.depths)):
|
| 94 |
+
for layer_idx in range(config.backbone_config.depths[stage_idx]):
|
| 95 |
+
# shortcut
|
| 96 |
+
if layer_idx == 0:
|
| 97 |
+
rename_keys.append(
|
| 98 |
+
(
|
| 99 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.shortcut.weight",
|
| 100 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.convolution.weight",
|
| 101 |
+
)
|
| 102 |
+
)
|
| 103 |
+
rename_keys.append(
|
| 104 |
+
(
|
| 105 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.shortcut.norm.weight",
|
| 106 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.normalization.weight",
|
| 107 |
+
)
|
| 108 |
+
)
|
| 109 |
+
rename_keys.append(
|
| 110 |
+
(
|
| 111 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.shortcut.norm.bias",
|
| 112 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.normalization.bias",
|
| 113 |
+
)
|
| 114 |
+
)
|
| 115 |
+
rename_keys.append(
|
| 116 |
+
(
|
| 117 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.shortcut.norm.running_mean",
|
| 118 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.normalization.running_mean",
|
| 119 |
+
)
|
| 120 |
+
)
|
| 121 |
+
rename_keys.append(
|
| 122 |
+
(
|
| 123 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.shortcut.norm.running_var",
|
| 124 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.normalization.running_var",
|
| 125 |
+
)
|
| 126 |
+
)
|
| 127 |
+
# 3 convs
|
| 128 |
+
for i in range(3):
|
| 129 |
+
rename_keys.append(
|
| 130 |
+
(
|
| 131 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.conv{i + 1}.weight",
|
| 132 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.convolution.weight",
|
| 133 |
+
)
|
| 134 |
+
)
|
| 135 |
+
rename_keys.append(
|
| 136 |
+
(
|
| 137 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.conv{i + 1}.norm.weight",
|
| 138 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.normalization.weight",
|
| 139 |
+
)
|
| 140 |
+
)
|
| 141 |
+
rename_keys.append(
|
| 142 |
+
(
|
| 143 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.conv{i + 1}.norm.bias",
|
| 144 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.normalization.bias",
|
| 145 |
+
)
|
| 146 |
+
)
|
| 147 |
+
rename_keys.append(
|
| 148 |
+
(
|
| 149 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.conv{i + 1}.norm.running_mean",
|
| 150 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.normalization.running_mean",
|
| 151 |
+
)
|
| 152 |
+
)
|
| 153 |
+
rename_keys.append(
|
| 154 |
+
(
|
| 155 |
+
f"backbone.res{stage_idx + 2}.{layer_idx}.conv{i + 1}.norm.running_var",
|
| 156 |
+
f"model.pixel_level_module.encoder.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.normalization.running_var",
|
| 157 |
+
)
|
| 158 |
+
)
|
| 159 |
+
|
| 160 |
+
# FPN
|
| 161 |
+
# fmt: off
|
| 162 |
+
rename_keys.append(("sem_seg_head.layer_4.weight", "model.pixel_level_module.decoder.fpn.stem.0.weight"))
|
| 163 |
+
rename_keys.append(("sem_seg_head.layer_4.norm.weight", "model.pixel_level_module.decoder.fpn.stem.1.weight"))
|
| 164 |
+
rename_keys.append(("sem_seg_head.layer_4.norm.bias", "model.pixel_level_module.decoder.fpn.stem.1.bias"))
|
| 165 |
+
for source_index, target_index in zip(range(3, 0, -1), range(0, 3)):
|
| 166 |
+
rename_keys.append((f"sem_seg_head.adapter_{source_index}.weight", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.0.weight"))
|
| 167 |
+
rename_keys.append((f"sem_seg_head.adapter_{source_index}.norm.weight", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.1.weight"))
|
| 168 |
+
rename_keys.append((f"sem_seg_head.adapter_{source_index}.norm.bias", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.1.bias"))
|
| 169 |
+
rename_keys.append((f"sem_seg_head.layer_{source_index}.weight", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.0.weight"))
|
| 170 |
+
rename_keys.append((f"sem_seg_head.layer_{source_index}.norm.weight", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.1.weight"))
|
| 171 |
+
rename_keys.append((f"sem_seg_head.layer_{source_index}.norm.bias", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.1.bias"))
|
| 172 |
+
rename_keys.append(("sem_seg_head.mask_features.weight", "model.pixel_level_module.decoder.mask_projection.weight"))
|
| 173 |
+
rename_keys.append(("sem_seg_head.mask_features.bias", "model.pixel_level_module.decoder.mask_projection.bias"))
|
| 174 |
+
# fmt: on
|
| 175 |
+
|
| 176 |
+
# Transformer decoder
|
| 177 |
+
# fmt: off
|
| 178 |
+
for idx in range(config.decoder_config.decoder_layers):
|
| 179 |
+
# self-attention out projection
|
| 180 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.out_proj.weight", f"model.transformer_module.decoder.layers.{idx}.self_attn.out_proj.weight"))
|
| 181 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.out_proj.bias", f"model.transformer_module.decoder.layers.{idx}.self_attn.out_proj.bias"))
|
| 182 |
+
# cross-attention out projection
|
| 183 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.out_proj.weight", f"model.transformer_module.decoder.layers.{idx}.encoder_attn.out_proj.weight"))
|
| 184 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.out_proj.bias", f"model.transformer_module.decoder.layers.{idx}.encoder_attn.out_proj.bias"))
|
| 185 |
+
# MLP 1
|
| 186 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear1.weight", f"model.transformer_module.decoder.layers.{idx}.fc1.weight"))
|
| 187 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear1.bias", f"model.transformer_module.decoder.layers.{idx}.fc1.bias"))
|
| 188 |
+
# MLP 2
|
| 189 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear2.weight", f"model.transformer_module.decoder.layers.{idx}.fc2.weight"))
|
| 190 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear2.bias", f"model.transformer_module.decoder.layers.{idx}.fc2.bias"))
|
| 191 |
+
# layernorm 1 (self-attention layernorm)
|
| 192 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm1.weight", f"model.transformer_module.decoder.layers.{idx}.self_attn_layer_norm.weight"))
|
| 193 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm1.bias", f"model.transformer_module.decoder.layers.{idx}.self_attn_layer_norm.bias"))
|
| 194 |
+
# layernorm 2 (cross-attention layernorm)
|
| 195 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm2.weight", f"model.transformer_module.decoder.layers.{idx}.encoder_attn_layer_norm.weight"))
|
| 196 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm2.bias", f"model.transformer_module.decoder.layers.{idx}.encoder_attn_layer_norm.bias"))
|
| 197 |
+
# layernorm 3 (final layernorm)
|
| 198 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm3.weight", f"model.transformer_module.decoder.layers.{idx}.final_layer_norm.weight"))
|
| 199 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm3.bias", f"model.transformer_module.decoder.layers.{idx}.final_layer_norm.bias"))
|
| 200 |
+
|
| 201 |
+
rename_keys.append(("sem_seg_head.predictor.transformer.decoder.norm.weight", "model.transformer_module.decoder.layernorm.weight"))
|
| 202 |
+
rename_keys.append(("sem_seg_head.predictor.transformer.decoder.norm.bias", "model.transformer_module.decoder.layernorm.bias"))
|
| 203 |
+
# fmt: on
|
| 204 |
+
|
| 205 |
+
# heads on top
|
| 206 |
+
# fmt: off
|
| 207 |
+
rename_keys.append(("sem_seg_head.predictor.query_embed.weight", "model.transformer_module.queries_embedder.weight"))
|
| 208 |
+
|
| 209 |
+
rename_keys.append(("sem_seg_head.predictor.input_proj.weight", "model.transformer_module.input_projection.weight"))
|
| 210 |
+
rename_keys.append(("sem_seg_head.predictor.input_proj.bias", "model.transformer_module.input_projection.bias"))
|
| 211 |
+
|
| 212 |
+
rename_keys.append(("sem_seg_head.predictor.class_embed.weight", "class_predictor.weight"))
|
| 213 |
+
rename_keys.append(("sem_seg_head.predictor.class_embed.bias", "class_predictor.bias"))
|
| 214 |
+
|
| 215 |
+
for i in range(3):
|
| 216 |
+
rename_keys.append((f"sem_seg_head.predictor.mask_embed.layers.{i}.weight", f"mask_embedder.{i}.0.weight"))
|
| 217 |
+
rename_keys.append((f"sem_seg_head.predictor.mask_embed.layers.{i}.bias", f"mask_embedder.{i}.0.bias"))
|
| 218 |
+
# fmt: on
|
| 219 |
+
|
| 220 |
+
return rename_keys
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
def rename_key(dct, old, new):
|
| 224 |
+
val = dct.pop(old)
|
| 225 |
+
dct[new] = val
|
| 226 |
+
|
| 227 |
+
|
| 228 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 229 |
+
def read_in_decoder_q_k_v(state_dict, config):
|
| 230 |
+
# fmt: off
|
| 231 |
+
hidden_size = config.decoder_config.hidden_size
|
| 232 |
+
for idx in range(config.decoder_config.decoder_layers):
|
| 233 |
+
# read in weights + bias of self-attention input projection layer (in the original implementation, this is a single matrix + bias)
|
| 234 |
+
in_proj_weight = state_dict.pop(f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.in_proj_weight")
|
| 235 |
+
in_proj_bias = state_dict.pop(f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.in_proj_bias")
|
| 236 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 237 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.q_proj.weight"] = in_proj_weight[: hidden_size, :]
|
| 238 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.q_proj.bias"] = in_proj_bias[:config.hidden_size]
|
| 239 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.k_proj.weight"] = in_proj_weight[hidden_size : hidden_size * 2, :]
|
| 240 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.k_proj.bias"] = in_proj_bias[hidden_size : hidden_size * 2]
|
| 241 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.v_proj.weight"] = in_proj_weight[-hidden_size :, :]
|
| 242 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.v_proj.bias"] = in_proj_bias[-hidden_size :]
|
| 243 |
+
# read in weights + bias of cross-attention input projection layer (in the original implementation, this is a single matrix + bias)
|
| 244 |
+
in_proj_weight = state_dict.pop(f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.in_proj_weight")
|
| 245 |
+
in_proj_bias = state_dict.pop(f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.in_proj_bias")
|
| 246 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 247 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.q_proj.weight"] = in_proj_weight[: hidden_size, :]
|
| 248 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.q_proj.bias"] = in_proj_bias[:config.hidden_size]
|
| 249 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.k_proj.weight"] = in_proj_weight[hidden_size : hidden_size * 2, :]
|
| 250 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.k_proj.bias"] = in_proj_bias[hidden_size : hidden_size * 2]
|
| 251 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.v_proj.weight"] = in_proj_weight[-hidden_size :, :]
|
| 252 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.v_proj.bias"] = in_proj_bias[-hidden_size :]
|
| 253 |
+
# fmt: on
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
# We will verify our results on an image of cute cats
|
| 257 |
+
def prepare_img() -> torch.Tensor:
|
| 258 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 259 |
+
with httpx.stream("GET", url) as response:
|
| 260 |
+
image = Image.open(BytesIO(response.read()))
|
| 261 |
+
return image
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
@torch.no_grad()
|
| 265 |
+
def convert_maskformer_checkpoint(
|
| 266 |
+
model_name: str, checkpoint_path: str, pytorch_dump_folder_path: str, push_to_hub: bool = False
|
| 267 |
+
):
|
| 268 |
+
"""
|
| 269 |
+
Copy/paste/tweak model's weights to our MaskFormer structure.
|
| 270 |
+
"""
|
| 271 |
+
config = get_maskformer_config(model_name)
|
| 272 |
+
|
| 273 |
+
if not strtobool(os.environ.get("TRUST_REMOTE_CODE", "False")):
|
| 274 |
+
raise ValueError(
|
| 275 |
+
"This part uses `pickle.load` which is insecure and will execute arbitrary code that is potentially "
|
| 276 |
+
"malicious. It's recommended to never unpickle data that could have come from an untrusted source, or "
|
| 277 |
+
"that could have been tampered with. If you already verified the pickle data and decided to use it, "
|
| 278 |
+
"you can set the environment variable `TRUST_REMOTE_CODE` to `True` to allow it."
|
| 279 |
+
)
|
| 280 |
+
# load original state_dict
|
| 281 |
+
with open(checkpoint_path, "rb") as f:
|
| 282 |
+
data = pickle.load(f)
|
| 283 |
+
state_dict = data["model"]
|
| 284 |
+
|
| 285 |
+
# rename keys
|
| 286 |
+
rename_keys = create_rename_keys(config)
|
| 287 |
+
for src, dest in rename_keys:
|
| 288 |
+
rename_key(state_dict, src, dest)
|
| 289 |
+
read_in_decoder_q_k_v(state_dict, config)
|
| 290 |
+
|
| 291 |
+
# update to torch tensors
|
| 292 |
+
for key, value in state_dict.items():
|
| 293 |
+
state_dict[key] = torch.from_numpy(value)
|
| 294 |
+
|
| 295 |
+
# load 🤗 model
|
| 296 |
+
model = MaskFormerForInstanceSegmentation(config)
|
| 297 |
+
model.eval()
|
| 298 |
+
|
| 299 |
+
model.load_state_dict(state_dict)
|
| 300 |
+
|
| 301 |
+
# verify results
|
| 302 |
+
image = prepare_img()
|
| 303 |
+
if "vistas" in model_name:
|
| 304 |
+
ignore_index = 65
|
| 305 |
+
elif "cityscapes" in model_name:
|
| 306 |
+
ignore_index = 65535
|
| 307 |
+
else:
|
| 308 |
+
ignore_index = 255
|
| 309 |
+
do_reduce_labels = "ade" in model_name
|
| 310 |
+
image_processor = MaskFormerImageProcessor(ignore_index=ignore_index, do_reduce_labels=do_reduce_labels)
|
| 311 |
+
|
| 312 |
+
inputs = image_processor(image, return_tensors="pt")
|
| 313 |
+
|
| 314 |
+
outputs = model(**inputs)
|
| 315 |
+
|
| 316 |
+
if model_name == "maskformer-resnet50-ade":
|
| 317 |
+
expected_logits = torch.tensor(
|
| 318 |
+
[[6.7710, -0.1452, -3.5687], [1.9165, -1.0010, -1.8614], [3.6209, -0.2950, -1.3813]]
|
| 319 |
+
)
|
| 320 |
+
elif model_name == "maskformer-resnet101-ade":
|
| 321 |
+
expected_logits = torch.tensor(
|
| 322 |
+
[[4.0381, -1.1483, -1.9688], [2.7083, -1.9147, -2.2555], [3.4367, -1.3711, -2.1609]]
|
| 323 |
+
)
|
| 324 |
+
elif model_name == "maskformer-resnet50-coco-stuff":
|
| 325 |
+
expected_logits = torch.tensor(
|
| 326 |
+
[[3.2309, -3.0481, -2.8695], [5.4986, -5.4242, -2.4211], [6.2100, -5.2279, -2.7786]]
|
| 327 |
+
)
|
| 328 |
+
elif model_name == "maskformer-resnet101-coco-stuff":
|
| 329 |
+
expected_logits = torch.tensor(
|
| 330 |
+
[[4.7188, -3.2585, -2.8857], [6.6871, -2.9181, -1.2487], [7.2449, -2.2764, -2.1874]]
|
| 331 |
+
)
|
| 332 |
+
elif model_name == "maskformer-resnet101-cityscapes":
|
| 333 |
+
expected_logits = torch.tensor(
|
| 334 |
+
[[-1.8861, -1.5465, 0.6749], [-2.3677, -1.6707, -0.0867], [-2.2314, -1.9530, -0.9132]]
|
| 335 |
+
)
|
| 336 |
+
elif model_name == "maskformer-resnet50-vistas":
|
| 337 |
+
expected_logits = torch.tensor(
|
| 338 |
+
[[-6.3917, -1.5216, -1.1392], [-5.5335, -4.5318, -1.8339], [-4.3576, -4.0301, 0.2162]]
|
| 339 |
+
)
|
| 340 |
+
elif model_name == "maskformer-resnet50-ade20k-full":
|
| 341 |
+
expected_logits = torch.tensor(
|
| 342 |
+
[[3.6146, -1.9367, -3.2534], [4.0099, 0.2027, -2.7576], [3.3913, -2.3644, -3.9519]]
|
| 343 |
+
)
|
| 344 |
+
elif model_name == "maskformer-resnet101-ade20k-full":
|
| 345 |
+
expected_logits = torch.tensor(
|
| 346 |
+
[[3.2211, -1.6550, -2.7605], [2.8559, -2.4512, -2.9574], [2.6331, -2.6775, -2.1844]]
|
| 347 |
+
)
|
| 348 |
+
|
| 349 |
+
assert torch.allclose(outputs.class_queries_logits[0, :3, :3], expected_logits, atol=1e-4)
|
| 350 |
+
print("Looks ok!")
|
| 351 |
+
|
| 352 |
+
if pytorch_dump_folder_path is not None:
|
| 353 |
+
print(f"Saving model and image processor of {model_name} to {pytorch_dump_folder_path}")
|
| 354 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 355 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 356 |
+
image_processor.save_pretrained(pytorch_dump_folder_path)
|
| 357 |
+
|
| 358 |
+
if push_to_hub:
|
| 359 |
+
print(f"Pushing model and image processor of {model_name} to the hub...")
|
| 360 |
+
model.push_to_hub(f"facebook/{model_name}")
|
| 361 |
+
image_processor.push_to_hub(f"facebook/{model_name}")
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
if __name__ == "__main__":
|
| 365 |
+
parser = argparse.ArgumentParser()
|
| 366 |
+
# Required parameters
|
| 367 |
+
parser.add_argument(
|
| 368 |
+
"--model_name",
|
| 369 |
+
default="maskformer-resnet50-ade",
|
| 370 |
+
type=str,
|
| 371 |
+
required=True,
|
| 372 |
+
choices=[
|
| 373 |
+
"maskformer-resnet50-ade",
|
| 374 |
+
"maskformer-resnet101-ade",
|
| 375 |
+
"maskformer-resnet50-coco-stuff",
|
| 376 |
+
"maskformer-resnet101-coco-stuff",
|
| 377 |
+
"maskformer-resnet101-cityscapes",
|
| 378 |
+
"maskformer-resnet50-vistas",
|
| 379 |
+
"maskformer-resnet50-ade20k-full",
|
| 380 |
+
"maskformer-resnet101-ade20k-full",
|
| 381 |
+
],
|
| 382 |
+
help=("Name of the MaskFormer model you'd like to convert",),
|
| 383 |
+
)
|
| 384 |
+
parser.add_argument(
|
| 385 |
+
"--checkpoint_path",
|
| 386 |
+
type=str,
|
| 387 |
+
required=True,
|
| 388 |
+
help="Path to the original pickle file (.pkl) of the original checkpoint.\n"
|
| 389 |
+
"Given the files are in the pickle format, please be wary of passing it files you trust.",
|
| 390 |
+
)
|
| 391 |
+
parser.add_argument(
|
| 392 |
+
"--pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model directory."
|
| 393 |
+
)
|
| 394 |
+
parser.add_argument(
|
| 395 |
+
"--push_to_hub",
|
| 396 |
+
action="store_true",
|
| 397 |
+
help="Whether or not to push the converted model to the Hugging Face hub.",
|
| 398 |
+
)
|
| 399 |
+
|
| 400 |
+
args = parser.parse_args()
|
| 401 |
+
convert_maskformer_checkpoint(
|
| 402 |
+
args.model_name, args.checkpoint_path, args.pytorch_dump_folder_path, args.push_to_hub
|
| 403 |
+
)
|
third_party/transformers/src/transformers/models/maskformer/convert_maskformer_swin_to_pytorch.py
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert MaskFormer checkpoints with Swin backbone from the original repository. URL:
|
| 15 |
+
https://github.com/facebookresearch/MaskFormer"""
|
| 16 |
+
|
| 17 |
+
import argparse
|
| 18 |
+
import json
|
| 19 |
+
import os
|
| 20 |
+
import pickle
|
| 21 |
+
from io import BytesIO
|
| 22 |
+
from pathlib import Path
|
| 23 |
+
|
| 24 |
+
import httpx
|
| 25 |
+
import torch
|
| 26 |
+
from huggingface_hub import hf_hub_download
|
| 27 |
+
from PIL import Image
|
| 28 |
+
|
| 29 |
+
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation, MaskFormerImageProcessor, SwinConfig
|
| 30 |
+
from transformers.utils import logging
|
| 31 |
+
|
| 32 |
+
from ...utils import strtobool
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
logging.set_verbosity_info()
|
| 36 |
+
logger = logging.get_logger(__name__)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def get_maskformer_config(model_name: str):
|
| 40 |
+
backbone_config = SwinConfig.from_pretrained(
|
| 41 |
+
"microsoft/swin-tiny-patch4-window7-224", out_features=["stage1", "stage2", "stage3", "stage4"]
|
| 42 |
+
)
|
| 43 |
+
config = MaskFormerConfig(backbone_config=backbone_config)
|
| 44 |
+
|
| 45 |
+
repo_id = "huggingface/label-files"
|
| 46 |
+
if "ade20k-full" in model_name:
|
| 47 |
+
# this should be ok
|
| 48 |
+
config.num_labels = 847
|
| 49 |
+
filename = "maskformer-ade20k-full-id2label.json"
|
| 50 |
+
elif "ade" in model_name:
|
| 51 |
+
# this should be ok
|
| 52 |
+
config.num_labels = 150
|
| 53 |
+
filename = "ade20k-id2label.json"
|
| 54 |
+
elif "coco-stuff" in model_name:
|
| 55 |
+
# this should be ok
|
| 56 |
+
config.num_labels = 171
|
| 57 |
+
filename = "maskformer-coco-stuff-id2label.json"
|
| 58 |
+
elif "coco" in model_name:
|
| 59 |
+
# TODO
|
| 60 |
+
config.num_labels = 133
|
| 61 |
+
filename = "coco-panoptic-id2label.json"
|
| 62 |
+
elif "cityscapes" in model_name:
|
| 63 |
+
# this should be ok
|
| 64 |
+
config.num_labels = 19
|
| 65 |
+
filename = "cityscapes-id2label.json"
|
| 66 |
+
elif "vistas" in model_name:
|
| 67 |
+
# this should be ok
|
| 68 |
+
config.num_labels = 65
|
| 69 |
+
filename = "mapillary-vistas-id2label.json"
|
| 70 |
+
|
| 71 |
+
id2label = json.load(open(hf_hub_download(repo_id, filename, repo_type="dataset"), "r"))
|
| 72 |
+
id2label = {int(k): v for k, v in id2label.items()}
|
| 73 |
+
|
| 74 |
+
return config
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def create_rename_keys(config):
|
| 78 |
+
rename_keys = []
|
| 79 |
+
# stem
|
| 80 |
+
# fmt: off
|
| 81 |
+
rename_keys.append(("backbone.patch_embed.proj.weight", "model.pixel_level_module.encoder.model.embeddings.patch_embeddings.projection.weight"))
|
| 82 |
+
rename_keys.append(("backbone.patch_embed.proj.bias", "model.pixel_level_module.encoder.model.embeddings.patch_embeddings.projection.bias"))
|
| 83 |
+
rename_keys.append(("backbone.patch_embed.norm.weight", "model.pixel_level_module.encoder.model.embeddings.norm.weight"))
|
| 84 |
+
rename_keys.append(("backbone.patch_embed.norm.bias", "model.pixel_level_module.encoder.model.embeddings.norm.bias"))
|
| 85 |
+
# stages
|
| 86 |
+
for i in range(len(config.backbone_config.depths)):
|
| 87 |
+
for j in range(config.backbone_config.depths[i]):
|
| 88 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.norm1.weight", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_before.weight"))
|
| 89 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.norm1.bias", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_before.bias"))
|
| 90 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.attn.relative_position_bias_table", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.relative_position_bias_table"))
|
| 91 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.attn.relative_position_index", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.relative_position_index"))
|
| 92 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.attn.proj.weight", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.output.dense.weight"))
|
| 93 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.attn.proj.bias", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.output.dense.bias"))
|
| 94 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.norm2.weight", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_after.weight"))
|
| 95 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.norm2.bias", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_after.bias"))
|
| 96 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.mlp.fc1.weight", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.intermediate.dense.weight"))
|
| 97 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.mlp.fc1.bias", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.intermediate.dense.bias"))
|
| 98 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.mlp.fc2.weight", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.output.dense.weight"))
|
| 99 |
+
rename_keys.append((f"backbone.layers.{i}.blocks.{j}.mlp.fc2.bias", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.output.dense.bias"))
|
| 100 |
+
|
| 101 |
+
if i < 3:
|
| 102 |
+
rename_keys.append((f"backbone.layers.{i}.downsample.reduction.weight", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.reduction.weight"))
|
| 103 |
+
rename_keys.append((f"backbone.layers.{i}.downsample.norm.weight", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.norm.weight"))
|
| 104 |
+
rename_keys.append((f"backbone.layers.{i}.downsample.norm.bias", f"model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.norm.bias"))
|
| 105 |
+
rename_keys.append((f"backbone.norm{i}.weight", f"model.pixel_level_module.encoder.hidden_states_norms.{i}.weight"))
|
| 106 |
+
rename_keys.append((f"backbone.norm{i}.bias", f"model.pixel_level_module.encoder.hidden_states_norms.{i}.bias"))
|
| 107 |
+
|
| 108 |
+
# FPN
|
| 109 |
+
rename_keys.append(("sem_seg_head.layer_4.weight", "model.pixel_level_module.decoder.fpn.stem.0.weight"))
|
| 110 |
+
rename_keys.append(("sem_seg_head.layer_4.norm.weight", "model.pixel_level_module.decoder.fpn.stem.1.weight"))
|
| 111 |
+
rename_keys.append(("sem_seg_head.layer_4.norm.bias", "model.pixel_level_module.decoder.fpn.stem.1.bias"))
|
| 112 |
+
for source_index, target_index in zip(range(3, 0, -1), range(0, 3)):
|
| 113 |
+
rename_keys.append((f"sem_seg_head.adapter_{source_index}.weight", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.0.weight"))
|
| 114 |
+
rename_keys.append((f"sem_seg_head.adapter_{source_index}.norm.weight", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.1.weight"))
|
| 115 |
+
rename_keys.append((f"sem_seg_head.adapter_{source_index}.norm.bias", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.1.bias"))
|
| 116 |
+
rename_keys.append((f"sem_seg_head.layer_{source_index}.weight", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.0.weight"))
|
| 117 |
+
rename_keys.append((f"sem_seg_head.layer_{source_index}.norm.weight", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.1.weight"))
|
| 118 |
+
rename_keys.append((f"sem_seg_head.layer_{source_index}.norm.bias", f"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.1.bias"))
|
| 119 |
+
rename_keys.append(("sem_seg_head.mask_features.weight", "model.pixel_level_module.decoder.mask_projection.weight"))
|
| 120 |
+
rename_keys.append(("sem_seg_head.mask_features.bias", "model.pixel_level_module.decoder.mask_projection.bias"))
|
| 121 |
+
|
| 122 |
+
# Transformer decoder
|
| 123 |
+
for idx in range(config.decoder_config.decoder_layers):
|
| 124 |
+
# self-attention out projection
|
| 125 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.out_proj.weight", f"model.transformer_module.decoder.layers.{idx}.self_attn.out_proj.weight"))
|
| 126 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.out_proj.bias", f"model.transformer_module.decoder.layers.{idx}.self_attn.out_proj.bias"))
|
| 127 |
+
# cross-attention out projection
|
| 128 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.out_proj.weight", f"model.transformer_module.decoder.layers.{idx}.encoder_attn.out_proj.weight"))
|
| 129 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.out_proj.bias", f"model.transformer_module.decoder.layers.{idx}.encoder_attn.out_proj.bias"))
|
| 130 |
+
# MLP 1
|
| 131 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear1.weight", f"model.transformer_module.decoder.layers.{idx}.fc1.weight"))
|
| 132 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear1.bias", f"model.transformer_module.decoder.layers.{idx}.fc1.bias"))
|
| 133 |
+
# MLP 2
|
| 134 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear2.weight", f"model.transformer_module.decoder.layers.{idx}.fc2.weight"))
|
| 135 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear2.bias", f"model.transformer_module.decoder.layers.{idx}.fc2.bias"))
|
| 136 |
+
# layernorm 1 (self-attention layernorm)
|
| 137 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm1.weight", f"model.transformer_module.decoder.layers.{idx}.self_attn_layer_norm.weight"))
|
| 138 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm1.bias", f"model.transformer_module.decoder.layers.{idx}.self_attn_layer_norm.bias"))
|
| 139 |
+
# layernorm 2 (cross-attention layernorm)
|
| 140 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm2.weight", f"model.transformer_module.decoder.layers.{idx}.encoder_attn_layer_norm.weight"))
|
| 141 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm2.bias", f"model.transformer_module.decoder.layers.{idx}.encoder_attn_layer_norm.bias"))
|
| 142 |
+
# layernorm 3 (final layernorm)
|
| 143 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm3.weight", f"model.transformer_module.decoder.layers.{idx}.final_layer_norm.weight"))
|
| 144 |
+
rename_keys.append((f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm3.bias", f"model.transformer_module.decoder.layers.{idx}.final_layer_norm.bias"))
|
| 145 |
+
|
| 146 |
+
rename_keys.append(("sem_seg_head.predictor.transformer.decoder.norm.weight", "model.transformer_module.decoder.layernorm.weight"))
|
| 147 |
+
rename_keys.append(("sem_seg_head.predictor.transformer.decoder.norm.bias", "model.transformer_module.decoder.layernorm.bias"))
|
| 148 |
+
|
| 149 |
+
# heads on top
|
| 150 |
+
rename_keys.append(("sem_seg_head.predictor.query_embed.weight", "model.transformer_module.queries_embedder.weight"))
|
| 151 |
+
|
| 152 |
+
rename_keys.append(("sem_seg_head.predictor.input_proj.weight", "model.transformer_module.input_projection.weight"))
|
| 153 |
+
rename_keys.append(("sem_seg_head.predictor.input_proj.bias", "model.transformer_module.input_projection.bias"))
|
| 154 |
+
|
| 155 |
+
rename_keys.append(("sem_seg_head.predictor.class_embed.weight", "class_predictor.weight"))
|
| 156 |
+
rename_keys.append(("sem_seg_head.predictor.class_embed.bias", "class_predictor.bias"))
|
| 157 |
+
|
| 158 |
+
for i in range(3):
|
| 159 |
+
rename_keys.append((f"sem_seg_head.predictor.mask_embed.layers.{i}.weight", f"mask_embedder.{i}.0.weight"))
|
| 160 |
+
rename_keys.append((f"sem_seg_head.predictor.mask_embed.layers.{i}.bias", f"mask_embedder.{i}.0.bias"))
|
| 161 |
+
# fmt: on
|
| 162 |
+
|
| 163 |
+
return rename_keys
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def rename_key(dct, old, new):
|
| 167 |
+
val = dct.pop(old)
|
| 168 |
+
dct[new] = val
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 172 |
+
def read_in_swin_q_k_v(state_dict, backbone_config):
|
| 173 |
+
num_features = [int(backbone_config.embed_dim * 2**i) for i in range(len(backbone_config.depths))]
|
| 174 |
+
for i in range(len(backbone_config.depths)):
|
| 175 |
+
dim = num_features[i]
|
| 176 |
+
for j in range(backbone_config.depths[i]):
|
| 177 |
+
# fmt: off
|
| 178 |
+
# read in weights + bias of input projection layer (in original implementation, this is a single matrix + bias)
|
| 179 |
+
in_proj_weight = state_dict.pop(f"backbone.layers.{i}.blocks.{j}.attn.qkv.weight")
|
| 180 |
+
in_proj_bias = state_dict.pop(f"backbone.layers.{i}.blocks.{j}.attn.qkv.bias")
|
| 181 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 182 |
+
state_dict[f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.query.weight"] = in_proj_weight[:dim, :]
|
| 183 |
+
state_dict[f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.query.bias"] = in_proj_bias[: dim]
|
| 184 |
+
state_dict[f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.key.weight"] = in_proj_weight[
|
| 185 |
+
dim : dim * 2, :
|
| 186 |
+
]
|
| 187 |
+
state_dict[f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.key.bias"] = in_proj_bias[
|
| 188 |
+
dim : dim * 2
|
| 189 |
+
]
|
| 190 |
+
state_dict[f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.value.weight"] = in_proj_weight[
|
| 191 |
+
-dim :, :
|
| 192 |
+
]
|
| 193 |
+
state_dict[f"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.value.bias"] = in_proj_bias[-dim :]
|
| 194 |
+
# fmt: on
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 198 |
+
def read_in_decoder_q_k_v(state_dict, config):
|
| 199 |
+
# fmt: off
|
| 200 |
+
hidden_size = config.decoder_config.hidden_size
|
| 201 |
+
for idx in range(config.decoder_config.decoder_layers):
|
| 202 |
+
# read in weights + bias of self-attention input projection layer (in the original implementation, this is a single matrix + bias)
|
| 203 |
+
in_proj_weight = state_dict.pop(f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.in_proj_weight")
|
| 204 |
+
in_proj_bias = state_dict.pop(f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.in_proj_bias")
|
| 205 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 206 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.q_proj.weight"] = in_proj_weight[: hidden_size, :]
|
| 207 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.q_proj.bias"] = in_proj_bias[:config.hidden_size]
|
| 208 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.k_proj.weight"] = in_proj_weight[hidden_size : hidden_size * 2, :]
|
| 209 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.k_proj.bias"] = in_proj_bias[hidden_size : hidden_size * 2]
|
| 210 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.v_proj.weight"] = in_proj_weight[-hidden_size :, :]
|
| 211 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.self_attn.v_proj.bias"] = in_proj_bias[-hidden_size :]
|
| 212 |
+
# read in weights + bias of cross-attention input projection layer (in the original implementation, this is a single matrix + bias)
|
| 213 |
+
in_proj_weight = state_dict.pop(f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.in_proj_weight")
|
| 214 |
+
in_proj_bias = state_dict.pop(f"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.in_proj_bias")
|
| 215 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 216 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.q_proj.weight"] = in_proj_weight[: hidden_size, :]
|
| 217 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.q_proj.bias"] = in_proj_bias[:config.hidden_size]
|
| 218 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.k_proj.weight"] = in_proj_weight[hidden_size : hidden_size * 2, :]
|
| 219 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.k_proj.bias"] = in_proj_bias[hidden_size : hidden_size * 2]
|
| 220 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.v_proj.weight"] = in_proj_weight[-hidden_size :, :]
|
| 221 |
+
state_dict[f"model.transformer_module.decoder.layers.{idx}.encoder_attn.v_proj.bias"] = in_proj_bias[-hidden_size :]
|
| 222 |
+
# fmt: on
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
# We will verify our results on an image of cute cats
|
| 226 |
+
def prepare_img() -> torch.Tensor:
|
| 227 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 228 |
+
with httpx.stream("GET", url) as response:
|
| 229 |
+
image = Image.open(BytesIO(response.read()))
|
| 230 |
+
return image
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
@torch.no_grad()
|
| 234 |
+
def convert_maskformer_checkpoint(
|
| 235 |
+
model_name: str, checkpoint_path: str, pytorch_dump_folder_path: str, push_to_hub: bool = False
|
| 236 |
+
):
|
| 237 |
+
"""
|
| 238 |
+
Copy/paste/tweak model's weights to our MaskFormer structure.
|
| 239 |
+
"""
|
| 240 |
+
config = get_maskformer_config(model_name)
|
| 241 |
+
|
| 242 |
+
if not strtobool(os.environ.get("TRUST_REMOTE_CODE", "False")):
|
| 243 |
+
raise ValueError(
|
| 244 |
+
"This part uses `pickle.load` which is insecure and will execute arbitrary code that is potentially "
|
| 245 |
+
"malicious. It's recommended to never unpickle data that could have come from an untrusted source, or "
|
| 246 |
+
"that could have been tampered with. If you already verified the pickle data and decided to use it, "
|
| 247 |
+
"you can set the environment variable `TRUST_REMOTE_CODE` to `True` to allow it."
|
| 248 |
+
)
|
| 249 |
+
# load original state_dict
|
| 250 |
+
with open(checkpoint_path, "rb") as f:
|
| 251 |
+
data = pickle.load(f)
|
| 252 |
+
state_dict = data["model"]
|
| 253 |
+
|
| 254 |
+
# for name, param in state_dict.items():
|
| 255 |
+
# print(name, param.shape)
|
| 256 |
+
|
| 257 |
+
# rename keys
|
| 258 |
+
rename_keys = create_rename_keys(config)
|
| 259 |
+
for src, dest in rename_keys:
|
| 260 |
+
rename_key(state_dict, src, dest)
|
| 261 |
+
read_in_swin_q_k_v(state_dict, config.backbone_config)
|
| 262 |
+
read_in_decoder_q_k_v(state_dict, config)
|
| 263 |
+
|
| 264 |
+
# update to torch tensors
|
| 265 |
+
for key, value in state_dict.items():
|
| 266 |
+
state_dict[key] = torch.from_numpy(value)
|
| 267 |
+
|
| 268 |
+
# load 🤗 model
|
| 269 |
+
model = MaskFormerForInstanceSegmentation(config)
|
| 270 |
+
model.eval()
|
| 271 |
+
|
| 272 |
+
for name, param in model.named_parameters():
|
| 273 |
+
print(name, param.shape)
|
| 274 |
+
|
| 275 |
+
missing_keys, unexpected_keys = model.load_state_dict(state_dict, strict=False)
|
| 276 |
+
assert missing_keys == [
|
| 277 |
+
"model.pixel_level_module.encoder.model.layernorm.weight",
|
| 278 |
+
"model.pixel_level_module.encoder.model.layernorm.bias",
|
| 279 |
+
]
|
| 280 |
+
assert len(unexpected_keys) == 0, f"Unexpected keys: {unexpected_keys}"
|
| 281 |
+
|
| 282 |
+
# verify results
|
| 283 |
+
image = prepare_img()
|
| 284 |
+
if "vistas" in model_name:
|
| 285 |
+
ignore_index = 65
|
| 286 |
+
elif "cityscapes" in model_name:
|
| 287 |
+
ignore_index = 65535
|
| 288 |
+
else:
|
| 289 |
+
ignore_index = 255
|
| 290 |
+
do_reduce_labels = "ade" in model_name
|
| 291 |
+
image_processor = MaskFormerImageProcessor(ignore_index=ignore_index, do_reduce_labels=do_reduce_labels)
|
| 292 |
+
|
| 293 |
+
inputs = image_processor(image, return_tensors="pt")
|
| 294 |
+
|
| 295 |
+
outputs = model(**inputs)
|
| 296 |
+
|
| 297 |
+
print("Logits:", outputs.class_queries_logits[0, :3, :3])
|
| 298 |
+
|
| 299 |
+
if model_name == "maskformer-swin-tiny-ade":
|
| 300 |
+
expected_logits = torch.tensor(
|
| 301 |
+
[[3.6353, -4.4770, -2.6065], [0.5081, -4.2394, -3.5343], [2.1909, -5.0353, -1.9323]]
|
| 302 |
+
)
|
| 303 |
+
assert torch.allclose(outputs.class_queries_logits[0, :3, :3], expected_logits, atol=1e-4)
|
| 304 |
+
print("Looks ok!")
|
| 305 |
+
|
| 306 |
+
if pytorch_dump_folder_path is not None:
|
| 307 |
+
print(f"Saving model and image processor to {pytorch_dump_folder_path}")
|
| 308 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 309 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 310 |
+
image_processor.save_pretrained(pytorch_dump_folder_path)
|
| 311 |
+
|
| 312 |
+
if push_to_hub:
|
| 313 |
+
print("Pushing model and image processor to the hub...")
|
| 314 |
+
model.push_to_hub(f"nielsr/{model_name}")
|
| 315 |
+
image_processor.push_to_hub(f"nielsr/{model_name}")
|
| 316 |
+
|
| 317 |
+
|
| 318 |
+
if __name__ == "__main__":
|
| 319 |
+
parser = argparse.ArgumentParser()
|
| 320 |
+
# Required parameters
|
| 321 |
+
parser.add_argument(
|
| 322 |
+
"--model_name",
|
| 323 |
+
default="maskformer-swin-tiny-ade",
|
| 324 |
+
type=str,
|
| 325 |
+
help=("Name of the MaskFormer model you'd like to convert",),
|
| 326 |
+
)
|
| 327 |
+
parser.add_argument(
|
| 328 |
+
"--checkpoint_path",
|
| 329 |
+
default="/Users/nielsrogge/Documents/MaskFormer_checkpoints/MaskFormer-Swin-tiny-ADE20k/model.pkl",
|
| 330 |
+
type=str,
|
| 331 |
+
help="Path to the original state dict (.pth file).\n"
|
| 332 |
+
"Given the files are in the pickle format, please be wary of passing it files you trust.",
|
| 333 |
+
)
|
| 334 |
+
parser.add_argument(
|
| 335 |
+
"--pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model directory."
|
| 336 |
+
)
|
| 337 |
+
parser.add_argument(
|
| 338 |
+
"--push_to_hub",
|
| 339 |
+
action="store_true",
|
| 340 |
+
help="Whether or not to push the converted model to the Hugging Face hub.",
|
| 341 |
+
)
|
| 342 |
+
|
| 343 |
+
args = parser.parse_args()
|
| 344 |
+
convert_maskformer_checkpoint(
|
| 345 |
+
args.model_name, args.checkpoint_path, args.pytorch_dump_folder_path, args.push_to_hub
|
| 346 |
+
)
|
third_party/transformers/src/transformers/models/maskformer/image_processing_maskformer.py
ADDED
|
@@ -0,0 +1,806 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Image processor class for MaskFormer."""
|
| 15 |
+
|
| 16 |
+
import math
|
| 17 |
+
from typing import Any, Optional, Union
|
| 18 |
+
|
| 19 |
+
import numpy as np
|
| 20 |
+
import torch
|
| 21 |
+
from torch import nn
|
| 22 |
+
from torchvision.transforms.v2 import functional as tvF
|
| 23 |
+
|
| 24 |
+
from ...image_processing_backends import TorchvisionBackend
|
| 25 |
+
from ...image_processing_utils import BatchFeature, get_size_dict
|
| 26 |
+
from ...image_transforms import get_size_with_aspect_ratio, group_images_by_shape, reorder_images
|
| 27 |
+
from ...image_utils import (
|
| 28 |
+
IMAGENET_DEFAULT_MEAN,
|
| 29 |
+
IMAGENET_DEFAULT_STD,
|
| 30 |
+
ChannelDimension,
|
| 31 |
+
ImageInput,
|
| 32 |
+
PILImageResampling,
|
| 33 |
+
SizeDict,
|
| 34 |
+
get_image_size_for_max_height_width,
|
| 35 |
+
)
|
| 36 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 37 |
+
from ...utils import TensorType, auto_docstring, logging
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
logger = logging.get_logger(__name__)
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
# Helper functions for post-processing (PyTorch-based)
|
| 44 |
+
def binary_mask_to_rle(mask: "torch.Tensor | np.ndarray") -> list[int]:
|
| 45 |
+
"""
|
| 46 |
+
Converts given binary mask of shape `(height, width)` to the run-length encoding (RLE) format.
|
| 47 |
+
|
| 48 |
+
Args:
|
| 49 |
+
mask (`torch.Tensor` or `np.ndarray`):
|
| 50 |
+
A binary mask of shape `(height, width)` where 0 denotes background and 1 denotes the target
|
| 51 |
+
segment_id or class_id.
|
| 52 |
+
Returns:
|
| 53 |
+
`List`: Run-length encoded list of the binary mask. Refer to COCO API for more information about the RLE
|
| 54 |
+
format.
|
| 55 |
+
"""
|
| 56 |
+
if isinstance(mask, np.ndarray):
|
| 57 |
+
mask = torch.from_numpy(mask)
|
| 58 |
+
|
| 59 |
+
pixels = mask.flatten()
|
| 60 |
+
zero = torch.zeros(1, device=pixels.device, dtype=pixels.dtype)
|
| 61 |
+
pixels = torch.cat([zero, pixels, zero])
|
| 62 |
+
runs = torch.where(pixels[1:] != pixels[:-1])[0] + 1
|
| 63 |
+
runs[1::2] -= runs[::2]
|
| 64 |
+
return runs.tolist()
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def convert_segmentation_to_rle(segmentation):
|
| 68 |
+
"""
|
| 69 |
+
Converts given segmentation map of shape `(height, width)` to the run-length encoding (RLE) format.
|
| 70 |
+
|
| 71 |
+
Args:
|
| 72 |
+
segmentation (`torch.Tensor`):
|
| 73 |
+
A segmentation map of shape `(height, width)` where each value denotes a segment or class id.
|
| 74 |
+
Returns:
|
| 75 |
+
`list[List]`: A list of lists, where each list is the run-length encoding of a segment / class id.
|
| 76 |
+
"""
|
| 77 |
+
segment_ids = torch.unique(segmentation)
|
| 78 |
+
|
| 79 |
+
run_length_encodings = []
|
| 80 |
+
for idx in segment_ids:
|
| 81 |
+
mask = torch.where(segmentation == idx, 1, 0)
|
| 82 |
+
rle = binary_mask_to_rle(mask)
|
| 83 |
+
run_length_encodings.append(rle)
|
| 84 |
+
|
| 85 |
+
return run_length_encodings
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def remove_low_and_no_objects(masks, scores, labels, object_mask_threshold, num_labels):
|
| 89 |
+
"""
|
| 90 |
+
Binarize the given masks using `object_mask_threshold`, it returns the associated values of `masks`, `scores` and
|
| 91 |
+
`labels`.
|
| 92 |
+
|
| 93 |
+
Args:
|
| 94 |
+
masks (`torch.Tensor`):
|
| 95 |
+
A tensor of shape `(num_queries, height, width)`.
|
| 96 |
+
scores (`torch.Tensor`):
|
| 97 |
+
A tensor of shape `(num_queries)`.
|
| 98 |
+
labels (`torch.Tensor`):
|
| 99 |
+
A tensor of shape `(num_queries)`.
|
| 100 |
+
object_mask_threshold (`float`):
|
| 101 |
+
A number between 0 and 1 used to binarize the masks.
|
| 102 |
+
Raises:
|
| 103 |
+
`ValueError`: Raised when the first dimension doesn't match in all input tensors.
|
| 104 |
+
Returns:
|
| 105 |
+
`tuple[`torch.Tensor`, `torch.Tensor`, `torch.Tensor`]`: The `masks`, `scores` and `labels` without the region
|
| 106 |
+
< `object_mask_threshold`.
|
| 107 |
+
"""
|
| 108 |
+
if not (masks.shape[0] == scores.shape[0] == labels.shape[0]):
|
| 109 |
+
raise ValueError("mask, scores and labels must have the same shape!")
|
| 110 |
+
|
| 111 |
+
to_keep = labels.ne(num_labels) & (scores > object_mask_threshold)
|
| 112 |
+
|
| 113 |
+
return masks[to_keep], scores[to_keep], labels[to_keep]
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def check_segment_validity(mask_labels, mask_probs, k, mask_threshold=0.5, overlap_mask_area_threshold=0.8):
|
| 117 |
+
# Get the mask associated with the k class
|
| 118 |
+
mask_k = mask_labels == k
|
| 119 |
+
mask_k_area = mask_k.sum()
|
| 120 |
+
|
| 121 |
+
# Compute the area of all the stuff in query k
|
| 122 |
+
original_area = (mask_probs[k] >= mask_threshold).sum()
|
| 123 |
+
mask_exists = mask_k_area > 0 and original_area > 0
|
| 124 |
+
|
| 125 |
+
# Eliminate disconnected tiny segments
|
| 126 |
+
if mask_exists:
|
| 127 |
+
area_ratio = mask_k_area / original_area
|
| 128 |
+
if not area_ratio.item() > overlap_mask_area_threshold:
|
| 129 |
+
mask_exists = False
|
| 130 |
+
|
| 131 |
+
return mask_exists, mask_k
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def compute_segments(
|
| 135 |
+
mask_probs,
|
| 136 |
+
pred_scores,
|
| 137 |
+
pred_labels,
|
| 138 |
+
mask_threshold: float = 0.5,
|
| 139 |
+
overlap_mask_area_threshold: float = 0.8,
|
| 140 |
+
label_ids_to_fuse: set[int] | None = None,
|
| 141 |
+
target_size: tuple[int, int] | None = None,
|
| 142 |
+
):
|
| 143 |
+
height = mask_probs.shape[1] if target_size is None else target_size[0]
|
| 144 |
+
width = mask_probs.shape[2] if target_size is None else target_size[1]
|
| 145 |
+
|
| 146 |
+
segmentation = torch.zeros((height, width), dtype=torch.int32, device=mask_probs.device)
|
| 147 |
+
segments: list[dict] = []
|
| 148 |
+
|
| 149 |
+
if target_size is not None:
|
| 150 |
+
mask_probs = nn.functional.interpolate(
|
| 151 |
+
mask_probs.unsqueeze(0), size=target_size, mode="bilinear", align_corners=False
|
| 152 |
+
)[0]
|
| 153 |
+
|
| 154 |
+
current_segment_id = 0
|
| 155 |
+
|
| 156 |
+
# Weigh each mask by its prediction score
|
| 157 |
+
mask_probs *= pred_scores.view(-1, 1, 1)
|
| 158 |
+
mask_labels = mask_probs.argmax(0) # [height, width]
|
| 159 |
+
|
| 160 |
+
# Keep track of instances of each class
|
| 161 |
+
stuff_memory_list: dict[str, int] = {}
|
| 162 |
+
for k in range(pred_labels.shape[0]):
|
| 163 |
+
pred_class = pred_labels[k].item()
|
| 164 |
+
should_fuse = pred_class in label_ids_to_fuse
|
| 165 |
+
|
| 166 |
+
# Check if mask exists and large enough to be a segment
|
| 167 |
+
mask_exists, mask_k = check_segment_validity(
|
| 168 |
+
mask_labels, mask_probs, k, mask_threshold, overlap_mask_area_threshold
|
| 169 |
+
)
|
| 170 |
+
|
| 171 |
+
if mask_exists:
|
| 172 |
+
if pred_class in stuff_memory_list:
|
| 173 |
+
current_segment_id = stuff_memory_list[pred_class]
|
| 174 |
+
else:
|
| 175 |
+
current_segment_id += 1
|
| 176 |
+
|
| 177 |
+
# Add current object segment to final segmentation map
|
| 178 |
+
segmentation[mask_k] = current_segment_id
|
| 179 |
+
segment_score = round(pred_scores[k].item(), 6)
|
| 180 |
+
segments.append(
|
| 181 |
+
{
|
| 182 |
+
"id": current_segment_id,
|
| 183 |
+
"label_id": pred_class,
|
| 184 |
+
"was_fused": should_fuse,
|
| 185 |
+
"score": segment_score,
|
| 186 |
+
}
|
| 187 |
+
)
|
| 188 |
+
if should_fuse:
|
| 189 |
+
stuff_memory_list[pred_class] = current_segment_id
|
| 190 |
+
|
| 191 |
+
return segmentation, segments
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
def convert_segmentation_map_to_binary_masks_fast(
|
| 195 |
+
segmentation_map: "torch.Tensor",
|
| 196 |
+
instance_id_to_semantic_id: dict[int, int] | None = None,
|
| 197 |
+
ignore_index: int | None = None,
|
| 198 |
+
do_reduce_labels: bool = False,
|
| 199 |
+
):
|
| 200 |
+
if do_reduce_labels and ignore_index is None:
|
| 201 |
+
raise ValueError("If `do_reduce_labels` is True, `ignore_index` must be provided.")
|
| 202 |
+
|
| 203 |
+
if do_reduce_labels:
|
| 204 |
+
segmentation_map = torch.where(segmentation_map == 0, ignore_index, segmentation_map - 1)
|
| 205 |
+
|
| 206 |
+
all_labels = torch.unique(segmentation_map)
|
| 207 |
+
|
| 208 |
+
if ignore_index is not None:
|
| 209 |
+
all_labels = all_labels[all_labels != ignore_index] # drop background label if applicable
|
| 210 |
+
|
| 211 |
+
binary_masks = [(segmentation_map == i) for i in all_labels]
|
| 212 |
+
if binary_masks:
|
| 213 |
+
binary_masks = torch.stack(binary_masks, dim=0)
|
| 214 |
+
else:
|
| 215 |
+
binary_masks = torch.zeros((0, *segmentation_map.shape), device=segmentation_map.device)
|
| 216 |
+
|
| 217 |
+
# Convert instance ids to class ids
|
| 218 |
+
if instance_id_to_semantic_id is not None:
|
| 219 |
+
labels = torch.zeros(all_labels.shape[0], device=segmentation_map.device)
|
| 220 |
+
|
| 221 |
+
for i, label in enumerate(all_labels):
|
| 222 |
+
class_id = instance_id_to_semantic_id[(label.item() + 1 if do_reduce_labels else label.item())]
|
| 223 |
+
labels[i] = class_id - 1 if do_reduce_labels else class_id
|
| 224 |
+
else:
|
| 225 |
+
labels = all_labels
|
| 226 |
+
return binary_masks.float(), labels.long()
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
class MaskFormerImageProcessorKwargs(ImagesKwargs, total=False):
|
| 230 |
+
r"""
|
| 231 |
+
ignore_index (`int`, *optional*):
|
| 232 |
+
Label to be assigned to background pixels in segmentation maps. If provided, segmentation map pixels
|
| 233 |
+
denoted with 0 (background) will be replaced with `ignore_index`.
|
| 234 |
+
do_reduce_labels (`bool`, *optional*, defaults to `False`):
|
| 235 |
+
Whether or not to decrement all label values of segmentation maps by 1. Usually used for datasets where 0
|
| 236 |
+
is used for background, and background itself is not included in all classes of a dataset (e.g. ADE20k).
|
| 237 |
+
The background label will be replaced by `ignore_index`.
|
| 238 |
+
num_labels (`int`, *optional*):
|
| 239 |
+
The number of labels in the segmentation map.
|
| 240 |
+
size_divisor (`int`, *optional*, defaults to `32`):
|
| 241 |
+
Some backbones need images divisible by a certain number. If not passed, it defaults to the value used in
|
| 242 |
+
Swin Transformer.
|
| 243 |
+
pad_size (`SizeDict`, *optional*):
|
| 244 |
+
The size to pad the images to. Must be larger than any image size provided for preprocessing. If `pad_size`
|
| 245 |
+
is not provided, images will be padded to the largest height and width in the batch.
|
| 246 |
+
"""
|
| 247 |
+
|
| 248 |
+
ignore_index: int | None
|
| 249 |
+
do_reduce_labels: bool
|
| 250 |
+
num_labels: int | None
|
| 251 |
+
size_divisor: int
|
| 252 |
+
pad_size: SizeDict | None
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
@auto_docstring
|
| 256 |
+
class MaskFormerImageProcessor(TorchvisionBackend):
|
| 257 |
+
valid_kwargs = MaskFormerImageProcessorKwargs
|
| 258 |
+
resample = PILImageResampling.BILINEAR
|
| 259 |
+
image_mean = IMAGENET_DEFAULT_MEAN
|
| 260 |
+
image_std = IMAGENET_DEFAULT_STD
|
| 261 |
+
size = {"shortest_edge": 800, "longest_edge": 1333}
|
| 262 |
+
default_to_square = False
|
| 263 |
+
do_resize = True
|
| 264 |
+
do_rescale = True
|
| 265 |
+
rescale_factor = 1 / 255
|
| 266 |
+
do_normalize = True
|
| 267 |
+
do_pad = True
|
| 268 |
+
model_input_names = ["pixel_values", "pixel_mask"]
|
| 269 |
+
size_divisor = 32
|
| 270 |
+
do_reduce_labels = False
|
| 271 |
+
|
| 272 |
+
def __init__(self, **kwargs: Unpack[MaskFormerImageProcessorKwargs]) -> None:
|
| 273 |
+
size = kwargs.pop("size", None)
|
| 274 |
+
max_size = kwargs.pop("max_size", None)
|
| 275 |
+
|
| 276 |
+
if size is None and max_size is not None:
|
| 277 |
+
size = self.size.copy()
|
| 278 |
+
size["longest_edge"] = max_size
|
| 279 |
+
elif size is None:
|
| 280 |
+
size = self.size
|
| 281 |
+
|
| 282 |
+
kwargs["size"] = get_size_dict(size, max_size=max_size, default_to_square=False)
|
| 283 |
+
super().__init__(**kwargs)
|
| 284 |
+
|
| 285 |
+
def to_dict(self) -> dict[str, Any]:
|
| 286 |
+
"""
|
| 287 |
+
Serializes this instance to a Python dictionary. This method calls the superclass method and then removes the
|
| 288 |
+
`_max_size` attribute from the dictionary.
|
| 289 |
+
"""
|
| 290 |
+
image_processor_dict = super().to_dict()
|
| 291 |
+
image_processor_dict.pop("_max_size", None)
|
| 292 |
+
return image_processor_dict
|
| 293 |
+
|
| 294 |
+
def reduce_label(self, labels: list["torch.Tensor"]):
|
| 295 |
+
for idx in range(len(labels)):
|
| 296 |
+
label = labels[idx]
|
| 297 |
+
label = torch.where(label == 0, torch.tensor(255, dtype=label.dtype), label)
|
| 298 |
+
label = label - 1
|
| 299 |
+
label = torch.where(label == 254, torch.tensor(255, dtype=label.dtype), label)
|
| 300 |
+
labels[idx] = label
|
| 301 |
+
|
| 302 |
+
def resize(
|
| 303 |
+
self,
|
| 304 |
+
image: torch.Tensor,
|
| 305 |
+
size: SizeDict,
|
| 306 |
+
size_divisor: int = 0,
|
| 307 |
+
resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None,
|
| 308 |
+
**kwargs,
|
| 309 |
+
) -> torch.Tensor:
|
| 310 |
+
"""
|
| 311 |
+
Resize the image to the given size. Size can be `min_size` (scalar) or `(height, width)` tuple. If size is an
|
| 312 |
+
int, smaller edge of the image will be matched to this number.
|
| 313 |
+
|
| 314 |
+
Args:
|
| 315 |
+
image (`torch.Tensor`):
|
| 316 |
+
Image to resize.
|
| 317 |
+
size (`SizeDict`):
|
| 318 |
+
Size of the image's `(height, width)` dimensions after resizing.
|
| 319 |
+
size_divisor (`int`, *optional*, defaults to 0):
|
| 320 |
+
If `size_divisor` is given, the output image size will be divisible by the number.
|
| 321 |
+
resample (`PILImageResampling | tvF.InterpolationMode | int | None`, *optional*):
|
| 322 |
+
Resampling filter to use if resizing the image.
|
| 323 |
+
"""
|
| 324 |
+
|
| 325 |
+
if size.shortest_edge and size.longest_edge:
|
| 326 |
+
# Resize the image so that the shortest edge or the longest edge is of the given size
|
| 327 |
+
# while maintaining the aspect ratio of the original image.
|
| 328 |
+
new_size = get_size_with_aspect_ratio(
|
| 329 |
+
image.size()[-2:],
|
| 330 |
+
size.shortest_edge,
|
| 331 |
+
size.longest_edge,
|
| 332 |
+
)
|
| 333 |
+
elif size.max_height and size.max_width:
|
| 334 |
+
new_size = get_image_size_for_max_height_width(image.size()[-2:], size.max_height, size.max_width)
|
| 335 |
+
elif size.height and size.width:
|
| 336 |
+
new_size = (size.height, size.width)
|
| 337 |
+
else:
|
| 338 |
+
raise ValueError(
|
| 339 |
+
f"Size must contain 'height' and 'width' keys or 'shortest_edge' and 'longest_edge' keys. Got {size}."
|
| 340 |
+
)
|
| 341 |
+
if size_divisor > 0:
|
| 342 |
+
height, width = new_size
|
| 343 |
+
height = int(math.ceil(height / size_divisor) * size_divisor)
|
| 344 |
+
width = int(math.ceil(width / size_divisor) * size_divisor)
|
| 345 |
+
new_size = (height, width)
|
| 346 |
+
|
| 347 |
+
image = super().resize(
|
| 348 |
+
image, size=SizeDict(height=new_size[0], width=new_size[1]), resample=resample, **kwargs
|
| 349 |
+
)
|
| 350 |
+
return image
|
| 351 |
+
|
| 352 |
+
def pad(
|
| 353 |
+
self,
|
| 354 |
+
images: torch.Tensor,
|
| 355 |
+
padded_size: tuple[int, int],
|
| 356 |
+
segmentation_maps: torch.Tensor | None = None,
|
| 357 |
+
fill: int = 0,
|
| 358 |
+
ignore_index: int = 255,
|
| 359 |
+
) -> tuple[torch.Tensor, torch.Tensor, list[torch.Tensor] | None]:
|
| 360 |
+
original_size = images.size()[-2:]
|
| 361 |
+
padding_bottom = padded_size[0] - original_size[0]
|
| 362 |
+
padding_right = padded_size[1] - original_size[1]
|
| 363 |
+
if padding_bottom < 0 or padding_right < 0:
|
| 364 |
+
raise ValueError(
|
| 365 |
+
f"Padding dimensions are negative. Please make sure that the padded size is larger than the "
|
| 366 |
+
f"original size. Got padded size: {padded_size}, original size: {original_size}."
|
| 367 |
+
)
|
| 368 |
+
if original_size != padded_size:
|
| 369 |
+
padding = [0, 0, padding_right, padding_bottom]
|
| 370 |
+
images = tvF.pad(images, padding, fill=fill)
|
| 371 |
+
if segmentation_maps is not None:
|
| 372 |
+
segmentation_maps = [tvF.pad(mask, padding, fill=ignore_index) for mask in segmentation_maps]
|
| 373 |
+
|
| 374 |
+
# Make a pixel mask for the image, where 1 indicates a valid pixel and 0 indicates padding.
|
| 375 |
+
pixel_mask = torch.zeros((images.shape[0], *padded_size), dtype=torch.int64, device=images.device)
|
| 376 |
+
pixel_mask[:, : original_size[0], : original_size[1]] = 1
|
| 377 |
+
|
| 378 |
+
return images, pixel_mask, segmentation_maps
|
| 379 |
+
|
| 380 |
+
@auto_docstring
|
| 381 |
+
def preprocess(
|
| 382 |
+
self,
|
| 383 |
+
images: ImageInput,
|
| 384 |
+
segmentation_maps: ImageInput | None = None,
|
| 385 |
+
instance_id_to_semantic_id: list[dict[int, int]] | dict[int, int] | None = None,
|
| 386 |
+
**kwargs: Unpack[MaskFormerImageProcessorKwargs],
|
| 387 |
+
) -> BatchFeature:
|
| 388 |
+
r"""
|
| 389 |
+
segmentation_maps (`ImageInput`, *optional*):
|
| 390 |
+
The segmentation maps.
|
| 391 |
+
instance_id_to_semantic_id (`Union[list[dict[int, int]], dict[int, int]]`, *optional*):
|
| 392 |
+
A mapping from instance IDs to semantic IDs.
|
| 393 |
+
"""
|
| 394 |
+
return super().preprocess(images, segmentation_maps, instance_id_to_semantic_id, **kwargs)
|
| 395 |
+
|
| 396 |
+
def _preprocess_image_like_inputs(
|
| 397 |
+
self,
|
| 398 |
+
images: ImageInput,
|
| 399 |
+
segmentation_maps: ImageInput,
|
| 400 |
+
instance_id_to_semantic_id: list[dict[int, int]] | dict[int, int] | None,
|
| 401 |
+
do_convert_rgb: bool,
|
| 402 |
+
input_data_format: ChannelDimension,
|
| 403 |
+
device: Union[str, "torch.device"] | None = None,
|
| 404 |
+
**kwargs: Unpack[MaskFormerImageProcessorKwargs],
|
| 405 |
+
) -> BatchFeature:
|
| 406 |
+
"""
|
| 407 |
+
Preprocess image-like inputs.
|
| 408 |
+
To be overridden by subclasses when image-like inputs other than images should be processed.
|
| 409 |
+
It can be used for segmentation maps, depth maps, etc.
|
| 410 |
+
"""
|
| 411 |
+
# Prepare input images
|
| 412 |
+
images = self._prepare_image_like_inputs(
|
| 413 |
+
images=images, do_convert_rgb=do_convert_rgb, input_data_format=input_data_format, device=device
|
| 414 |
+
)
|
| 415 |
+
if segmentation_maps is not None:
|
| 416 |
+
segmentation_maps = self._prepare_image_like_inputs(
|
| 417 |
+
images=segmentation_maps,
|
| 418 |
+
expected_ndims=2,
|
| 419 |
+
do_convert_rgb=False,
|
| 420 |
+
input_data_format=ChannelDimension.FIRST,
|
| 421 |
+
)
|
| 422 |
+
return self._preprocess(images, segmentation_maps, instance_id_to_semantic_id, **kwargs)
|
| 423 |
+
|
| 424 |
+
def _preprocess(
|
| 425 |
+
self,
|
| 426 |
+
images: list["torch.Tensor"],
|
| 427 |
+
segmentation_maps: Optional["torch.Tensor"],
|
| 428 |
+
instance_id_to_semantic_id: dict[int, int] | None,
|
| 429 |
+
do_resize: bool | None,
|
| 430 |
+
size: SizeDict | None,
|
| 431 |
+
pad_size: SizeDict | None,
|
| 432 |
+
size_divisor: int | None,
|
| 433 |
+
resample: Union["PILImageResampling", "tvF.InterpolationMode"] | None,
|
| 434 |
+
do_rescale: bool | None,
|
| 435 |
+
rescale_factor: float | None,
|
| 436 |
+
do_normalize: bool | None,
|
| 437 |
+
image_mean: float | list[float] | None,
|
| 438 |
+
image_std: float | list[float] | None,
|
| 439 |
+
ignore_index: int | None,
|
| 440 |
+
do_reduce_labels: bool | None,
|
| 441 |
+
disable_grouping: bool | None,
|
| 442 |
+
return_tensors: str | TensorType | None,
|
| 443 |
+
**kwargs,
|
| 444 |
+
) -> BatchFeature:
|
| 445 |
+
from ...image_utils import get_max_height_width
|
| 446 |
+
|
| 447 |
+
if segmentation_maps is not None and len(images) != len(segmentation_maps):
|
| 448 |
+
raise ValueError("Images and segmentation maps must have the same length.")
|
| 449 |
+
|
| 450 |
+
# Group images by size for batched resizing
|
| 451 |
+
grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
|
| 452 |
+
resized_images_grouped = {}
|
| 453 |
+
if segmentation_maps is not None:
|
| 454 |
+
grouped_segmentation_maps, grouped_segmentation_maps_index = group_images_by_shape(
|
| 455 |
+
segmentation_maps, disable_grouping=disable_grouping
|
| 456 |
+
)
|
| 457 |
+
resized_segmentation_maps_grouped = {}
|
| 458 |
+
for shape, stacked_images in grouped_images.items():
|
| 459 |
+
if do_resize:
|
| 460 |
+
stacked_images = self.resize(
|
| 461 |
+
image=stacked_images, size=size, size_divisor=size_divisor, resample=resample
|
| 462 |
+
)
|
| 463 |
+
if segmentation_maps is not None:
|
| 464 |
+
stacked_segmentation_maps = grouped_segmentation_maps[shape]
|
| 465 |
+
if do_resize:
|
| 466 |
+
stacked_segmentation_maps = self.resize(
|
| 467 |
+
image=stacked_segmentation_maps,
|
| 468 |
+
size=size,
|
| 469 |
+
size_divisor=size_divisor,
|
| 470 |
+
resample=tvF.InterpolationMode.NEAREST_EXACT,
|
| 471 |
+
)
|
| 472 |
+
resized_images_grouped[shape] = stacked_images
|
| 473 |
+
if segmentation_maps is not None:
|
| 474 |
+
resized_segmentation_maps_grouped[shape] = stacked_segmentation_maps
|
| 475 |
+
resized_images = reorder_images(resized_images_grouped, grouped_images_index)
|
| 476 |
+
if segmentation_maps is not None:
|
| 477 |
+
resized_segmentation_maps = reorder_images(
|
| 478 |
+
resized_segmentation_maps_grouped, grouped_segmentation_maps_index
|
| 479 |
+
)
|
| 480 |
+
if pad_size is not None:
|
| 481 |
+
padded_size = (pad_size.height, pad_size.width)
|
| 482 |
+
else:
|
| 483 |
+
padded_size = get_max_height_width(resized_images)
|
| 484 |
+
|
| 485 |
+
if segmentation_maps is not None:
|
| 486 |
+
mask_labels = []
|
| 487 |
+
class_labels = []
|
| 488 |
+
# Convert to list of binary masks and labels
|
| 489 |
+
for idx, segmentation_map in enumerate(resized_segmentation_maps):
|
| 490 |
+
if isinstance(instance_id_to_semantic_id, list):
|
| 491 |
+
instance_id = instance_id_to_semantic_id[idx]
|
| 492 |
+
else:
|
| 493 |
+
instance_id = instance_id_to_semantic_id
|
| 494 |
+
# Use instance2class_id mapping per image
|
| 495 |
+
masks, classes = convert_segmentation_map_to_binary_masks_fast(
|
| 496 |
+
segmentation_map.squeeze(0),
|
| 497 |
+
instance_id,
|
| 498 |
+
ignore_index=ignore_index,
|
| 499 |
+
do_reduce_labels=do_reduce_labels,
|
| 500 |
+
)
|
| 501 |
+
mask_labels.append(masks)
|
| 502 |
+
class_labels.append(classes)
|
| 503 |
+
|
| 504 |
+
if segmentation_maps is not None:
|
| 505 |
+
# group mask_labels as paired inputs and not images so as not to stack them
|
| 506 |
+
grouped_images, grouped_segmentation_maps, grouped_images_index = group_images_by_shape(
|
| 507 |
+
resized_images, mask_labels, disable_grouping=disable_grouping
|
| 508 |
+
)
|
| 509 |
+
processed_segmentation_maps_grouped = {}
|
| 510 |
+
else:
|
| 511 |
+
grouped_images, grouped_images_index = group_images_by_shape(
|
| 512 |
+
resized_images, disable_grouping=disable_grouping
|
| 513 |
+
)
|
| 514 |
+
processed_images_grouped = {}
|
| 515 |
+
processed_pixel_masks_grouped = {}
|
| 516 |
+
for shape, stacked_images in grouped_images.items():
|
| 517 |
+
# Fused rescale and normalize
|
| 518 |
+
stacked_images = self.rescale_and_normalize(
|
| 519 |
+
stacked_images, do_rescale, rescale_factor, do_normalize, image_mean, image_std
|
| 520 |
+
)
|
| 521 |
+
padded_images, pixel_masks, padded_segmentation_maps = self.pad(
|
| 522 |
+
images=stacked_images,
|
| 523 |
+
segmentation_maps=grouped_segmentation_maps[shape] if segmentation_maps is not None else None,
|
| 524 |
+
padded_size=padded_size,
|
| 525 |
+
ignore_index=ignore_index,
|
| 526 |
+
)
|
| 527 |
+
processed_images_grouped[shape] = padded_images
|
| 528 |
+
processed_pixel_masks_grouped[shape] = pixel_masks
|
| 529 |
+
if segmentation_maps is not None:
|
| 530 |
+
processed_segmentation_maps_grouped[shape] = padded_segmentation_maps
|
| 531 |
+
|
| 532 |
+
processed_images = reorder_images(processed_images_grouped, grouped_images_index)
|
| 533 |
+
processed_pixel_masks = reorder_images(processed_pixel_masks_grouped, grouped_images_index)
|
| 534 |
+
encoded_inputs = BatchFeature(
|
| 535 |
+
data={"pixel_values": processed_images, "pixel_mask": processed_pixel_masks},
|
| 536 |
+
tensor_type=return_tensors,
|
| 537 |
+
)
|
| 538 |
+
if segmentation_maps is not None:
|
| 539 |
+
mask_labels = reorder_images(processed_segmentation_maps_grouped, grouped_images_index)
|
| 540 |
+
# we cannot batch them since they don't share a common class size
|
| 541 |
+
encoded_inputs["mask_labels"] = mask_labels
|
| 542 |
+
encoded_inputs["class_labels"] = class_labels
|
| 543 |
+
|
| 544 |
+
return encoded_inputs
|
| 545 |
+
|
| 546 |
+
# Copied from transformers.models.maskformer.image_processing_maskformer.MaskFormerImageProcessor.post_process_semantic_segmentation
|
| 547 |
+
def post_process_semantic_segmentation(
|
| 548 |
+
self, outputs, target_sizes: list[tuple[int, int]] | None = None
|
| 549 |
+
) -> "torch.Tensor":
|
| 550 |
+
"""
|
| 551 |
+
Converts the output of [`MaskFormerForInstanceSegmentation`] into semantic segmentation maps. Only supports
|
| 552 |
+
PyTorch.
|
| 553 |
+
|
| 554 |
+
Args:
|
| 555 |
+
outputs ([`MaskFormerForInstanceSegmentation`]):
|
| 556 |
+
Raw outputs of the model.
|
| 557 |
+
target_sizes (`list[tuple[int, int]]`, *optional*):
|
| 558 |
+
List of length (batch_size), where each list item (`tuple[int, int]]`) corresponds to the requested
|
| 559 |
+
final size (height, width) of each prediction. If left to None, predictions will not be resized.
|
| 560 |
+
Returns:
|
| 561 |
+
`list[torch.Tensor]`:
|
| 562 |
+
A list of length `batch_size`, where each item is a semantic segmentation map of shape (height, width)
|
| 563 |
+
corresponding to the target_sizes entry (if `target_sizes` is specified). Each entry of each
|
| 564 |
+
`torch.Tensor` correspond to a semantic class id.
|
| 565 |
+
"""
|
| 566 |
+
class_queries_logits = outputs.class_queries_logits # [batch_size, num_queries, num_classes+1]
|
| 567 |
+
masks_queries_logits = outputs.masks_queries_logits # [batch_size, num_queries, height, width]
|
| 568 |
+
|
| 569 |
+
# Remove the null class `[..., :-1]`
|
| 570 |
+
masks_classes = class_queries_logits.softmax(dim=-1)[..., :-1]
|
| 571 |
+
masks_probs = masks_queries_logits.sigmoid() # [batch_size, num_queries, height, width]
|
| 572 |
+
|
| 573 |
+
# Semantic segmentation logits of shape (batch_size, num_classes, height, width)
|
| 574 |
+
segmentation = torch.einsum("bqc, bqhw -> bchw", masks_classes, masks_probs)
|
| 575 |
+
batch_size = class_queries_logits.shape[0]
|
| 576 |
+
|
| 577 |
+
# Resize logits and compute semantic segmentation maps
|
| 578 |
+
if target_sizes is not None:
|
| 579 |
+
if batch_size != len(target_sizes):
|
| 580 |
+
raise ValueError(
|
| 581 |
+
"Make sure that you pass in as many target sizes as the batch dimension of the logits"
|
| 582 |
+
)
|
| 583 |
+
|
| 584 |
+
semantic_segmentation = []
|
| 585 |
+
for idx in range(batch_size):
|
| 586 |
+
resized_logits = torch.nn.functional.interpolate(
|
| 587 |
+
segmentation[idx].unsqueeze(dim=0), size=target_sizes[idx], mode="bilinear", align_corners=False
|
| 588 |
+
)
|
| 589 |
+
semantic_map = resized_logits[0].argmax(dim=0)
|
| 590 |
+
semantic_segmentation.append(semantic_map)
|
| 591 |
+
else:
|
| 592 |
+
semantic_segmentation = segmentation.argmax(dim=1)
|
| 593 |
+
semantic_segmentation = [semantic_segmentation[i] for i in range(semantic_segmentation.shape[0])]
|
| 594 |
+
|
| 595 |
+
return semantic_segmentation
|
| 596 |
+
|
| 597 |
+
# Copied from transformers.models.maskformer.image_processing_maskformer.MaskFormerImageProcessor.post_process_instance_segmentation
|
| 598 |
+
def post_process_instance_segmentation(
|
| 599 |
+
self,
|
| 600 |
+
outputs,
|
| 601 |
+
threshold: float = 0.5,
|
| 602 |
+
mask_threshold: float = 0.5,
|
| 603 |
+
overlap_mask_area_threshold: float = 0.8,
|
| 604 |
+
target_sizes: list[tuple[int, int]] | None = None,
|
| 605 |
+
return_coco_annotation: bool | None = False,
|
| 606 |
+
return_binary_maps: bool | None = False,
|
| 607 |
+
) -> list[dict]:
|
| 608 |
+
"""
|
| 609 |
+
Converts the output of [`MaskFormerForInstanceSegmentationOutput`] into instance segmentation predictions. Only
|
| 610 |
+
supports PyTorch. If instances could overlap, set either return_coco_annotation or return_binary_maps
|
| 611 |
+
to `True` to get the correct segmentation result.
|
| 612 |
+
|
| 613 |
+
Args:
|
| 614 |
+
outputs ([`MaskFormerForInstanceSegmentation`]):
|
| 615 |
+
Raw outputs of the model.
|
| 616 |
+
threshold (`float`, *optional*, defaults to 0.5):
|
| 617 |
+
The probability score threshold to keep predicted instance masks.
|
| 618 |
+
mask_threshold (`float`, *optional*, defaults to 0.5):
|
| 619 |
+
Threshold to use when turning the predicted masks into binary values.
|
| 620 |
+
overlap_mask_area_threshold (`float`, *optional*, defaults to 0.8):
|
| 621 |
+
The overlap mask area threshold to merge or discard small disconnected parts within each binary
|
| 622 |
+
instance mask.
|
| 623 |
+
target_sizes (`list[Tuple]`, *optional*):
|
| 624 |
+
List of length (batch_size), where each list item (`tuple[int, int]]`) corresponds to the requested
|
| 625 |
+
final size (height, width) of each prediction. If left to None, predictions will not be resized.
|
| 626 |
+
return_coco_annotation (`bool`, *optional*, defaults to `False`):
|
| 627 |
+
If set to `True`, segmentation maps are returned in COCO run-length encoding (RLE) format.
|
| 628 |
+
return_binary_maps (`bool`, *optional*, defaults to `False`):
|
| 629 |
+
If set to `True`, segmentation maps are returned as a concatenated tensor of binary segmentation maps
|
| 630 |
+
(one per detected instance).
|
| 631 |
+
Returns:
|
| 632 |
+
`list[Dict]`: A list of dictionaries, one per image, each dictionary containing two keys:
|
| 633 |
+
- **segmentation** -- A tensor of shape `(height, width)` where each pixel represents a `segment_id`, or
|
| 634 |
+
`list[List]` run-length encoding (RLE) of the segmentation map if return_coco_annotation is set to
|
| 635 |
+
`True`, or a tensor of shape `(num_instances, height, width)` if return_binary_maps is set to `True`.
|
| 636 |
+
Set to `None` if no mask if found above `threshold`.
|
| 637 |
+
- **segments_info** -- A dictionary that contains additional information on each segment.
|
| 638 |
+
- **id** -- An integer representing the `segment_id`.
|
| 639 |
+
- **label_id** -- An integer representing the label / semantic class id corresponding to `segment_id`.
|
| 640 |
+
- **score** -- Prediction score of segment with `segment_id`.
|
| 641 |
+
"""
|
| 642 |
+
if return_coco_annotation and return_binary_maps:
|
| 643 |
+
raise ValueError("return_coco_annotation and return_binary_maps can not be both set to True.")
|
| 644 |
+
|
| 645 |
+
# [batch_size, num_queries, num_classes+1]
|
| 646 |
+
class_queries_logits = outputs.class_queries_logits
|
| 647 |
+
# [batch_size, num_queries, height, width]
|
| 648 |
+
masks_queries_logits = outputs.masks_queries_logits
|
| 649 |
+
|
| 650 |
+
device = masks_queries_logits.device
|
| 651 |
+
num_classes = class_queries_logits.shape[-1] - 1
|
| 652 |
+
num_queries = class_queries_logits.shape[-2]
|
| 653 |
+
|
| 654 |
+
# Loop over items in batch size
|
| 655 |
+
results: list[dict[str, TensorType]] = []
|
| 656 |
+
|
| 657 |
+
for i in range(class_queries_logits.shape[0]):
|
| 658 |
+
mask_pred = masks_queries_logits[i]
|
| 659 |
+
mask_cls = class_queries_logits[i]
|
| 660 |
+
|
| 661 |
+
scores = torch.nn.functional.softmax(mask_cls, dim=-1)[:, :-1]
|
| 662 |
+
labels = torch.arange(num_classes, device=device).unsqueeze(0).repeat(num_queries, 1).flatten(0, 1)
|
| 663 |
+
|
| 664 |
+
scores_per_image, topk_indices = scores.flatten(0, 1).topk(num_queries, sorted=False)
|
| 665 |
+
labels_per_image = labels[topk_indices]
|
| 666 |
+
|
| 667 |
+
topk_indices = torch.div(topk_indices, num_classes, rounding_mode="floor")
|
| 668 |
+
mask_pred = mask_pred[topk_indices]
|
| 669 |
+
pred_masks = (mask_pred > 0).float()
|
| 670 |
+
|
| 671 |
+
# Calculate average mask prob
|
| 672 |
+
mask_scores_per_image = (mask_pred.sigmoid().flatten(1) * pred_masks.flatten(1)).sum(1) / (
|
| 673 |
+
pred_masks.flatten(1).sum(1) + 1e-6
|
| 674 |
+
)
|
| 675 |
+
pred_scores = scores_per_image * mask_scores_per_image
|
| 676 |
+
pred_classes = labels_per_image
|
| 677 |
+
|
| 678 |
+
segmentation = torch.zeros(masks_queries_logits.shape[2:]) - 1
|
| 679 |
+
if target_sizes is not None:
|
| 680 |
+
segmentation = torch.zeros(target_sizes[i]) - 1
|
| 681 |
+
pred_masks = torch.nn.functional.interpolate(
|
| 682 |
+
pred_masks.unsqueeze(0), size=target_sizes[i], mode="nearest"
|
| 683 |
+
)[0]
|
| 684 |
+
|
| 685 |
+
instance_maps, segments = [], []
|
| 686 |
+
current_segment_id = 0
|
| 687 |
+
for j in range(num_queries):
|
| 688 |
+
score = pred_scores[j].item()
|
| 689 |
+
|
| 690 |
+
if not torch.all(pred_masks[j] == 0) and score >= threshold:
|
| 691 |
+
segmentation[pred_masks[j] == 1] = current_segment_id
|
| 692 |
+
segments.append(
|
| 693 |
+
{
|
| 694 |
+
"id": current_segment_id,
|
| 695 |
+
"label_id": pred_classes[j].item(),
|
| 696 |
+
"was_fused": False,
|
| 697 |
+
"score": round(score, 6),
|
| 698 |
+
}
|
| 699 |
+
)
|
| 700 |
+
current_segment_id += 1
|
| 701 |
+
instance_maps.append(pred_masks[j])
|
| 702 |
+
|
| 703 |
+
# Return segmentation map in run-length encoding (RLE) format
|
| 704 |
+
if return_coco_annotation:
|
| 705 |
+
segmentation = convert_segmentation_to_rle(segmentation)
|
| 706 |
+
|
| 707 |
+
# Return a concatenated tensor of binary instance maps
|
| 708 |
+
if return_binary_maps and len(instance_maps) != 0:
|
| 709 |
+
segmentation = torch.stack(instance_maps, dim=0)
|
| 710 |
+
|
| 711 |
+
results.append({"segmentation": segmentation, "segments_info": segments})
|
| 712 |
+
return results
|
| 713 |
+
|
| 714 |
+
# Copied from transformers.models.maskformer.image_processing_maskformer.MaskFormerImageProcessor.post_process_panoptic_segmentation
|
| 715 |
+
def post_process_panoptic_segmentation(
|
| 716 |
+
self,
|
| 717 |
+
outputs,
|
| 718 |
+
threshold: float = 0.5,
|
| 719 |
+
mask_threshold: float = 0.5,
|
| 720 |
+
overlap_mask_area_threshold: float = 0.8,
|
| 721 |
+
label_ids_to_fuse: set[int] | None = None,
|
| 722 |
+
target_sizes: list[tuple[int, int]] | None = None,
|
| 723 |
+
) -> list[dict]:
|
| 724 |
+
"""
|
| 725 |
+
Converts the output of [`MaskFormerForInstanceSegmentationOutput`] into image panoptic segmentation
|
| 726 |
+
predictions. Only supports PyTorch.
|
| 727 |
+
|
| 728 |
+
Args:
|
| 729 |
+
outputs ([`MaskFormerForInstanceSegmentationOutput`]):
|
| 730 |
+
The outputs from [`MaskFormerForInstanceSegmentation`].
|
| 731 |
+
threshold (`float`, *optional*, defaults to 0.5):
|
| 732 |
+
The probability score threshold to keep predicted instance masks.
|
| 733 |
+
mask_threshold (`float`, *optional*, defaults to 0.5):
|
| 734 |
+
Threshold to use when turning the predicted masks into binary values.
|
| 735 |
+
overlap_mask_area_threshold (`float`, *optional*, defaults to 0.8):
|
| 736 |
+
The overlap mask area threshold to merge or discard small disconnected parts within each binary
|
| 737 |
+
instance mask.
|
| 738 |
+
label_ids_to_fuse (`Set[int]`, *optional*):
|
| 739 |
+
The labels in this state will have all their instances be fused together. For instance we could say
|
| 740 |
+
there can only be one sky in an image, but several persons, so the label ID for sky would be in that
|
| 741 |
+
set, but not the one for person.
|
| 742 |
+
target_sizes (`list[Tuple]`, *optional*):
|
| 743 |
+
List of length (batch_size), where each list item (`tuple[int, int]]`) corresponds to the requested
|
| 744 |
+
final size (height, width) of each prediction in batch. If left to None, predictions will not be
|
| 745 |
+
resized.
|
| 746 |
+
|
| 747 |
+
Returns:
|
| 748 |
+
`list[Dict]`: A list of dictionaries, one per image, each dictionary containing two keys:
|
| 749 |
+
- **segmentation** -- a tensor of shape `(height, width)` where each pixel represents a `segment_id`, set
|
| 750 |
+
to `None` if no mask if found above `threshold`. If `target_sizes` is specified, segmentation is resized
|
| 751 |
+
to the corresponding `target_sizes` entry.
|
| 752 |
+
- **segments_info** -- A dictionary that contains additional information on each segment.
|
| 753 |
+
- **id** -- an integer representing the `segment_id`.
|
| 754 |
+
- **label_id** -- An integer representing the label / semantic class id corresponding to `segment_id`.
|
| 755 |
+
- **was_fused** -- a boolean, `True` if `label_id` was in `label_ids_to_fuse`, `False` otherwise.
|
| 756 |
+
Multiple instances of the same class / label were fused and assigned a single `segment_id`.
|
| 757 |
+
- **score** -- Prediction score of segment with `segment_id`.
|
| 758 |
+
"""
|
| 759 |
+
|
| 760 |
+
if label_ids_to_fuse is None:
|
| 761 |
+
logger.warning("`label_ids_to_fuse` unset. No instance will be fused.")
|
| 762 |
+
label_ids_to_fuse = set()
|
| 763 |
+
|
| 764 |
+
class_queries_logits = outputs.class_queries_logits # [batch_size, num_queries, num_classes+1]
|
| 765 |
+
masks_queries_logits = outputs.masks_queries_logits # [batch_size, num_queries, height, width]
|
| 766 |
+
|
| 767 |
+
batch_size = class_queries_logits.shape[0]
|
| 768 |
+
num_labels = class_queries_logits.shape[-1] - 1
|
| 769 |
+
|
| 770 |
+
mask_probs = masks_queries_logits.sigmoid() # [batch_size, num_queries, height, width]
|
| 771 |
+
|
| 772 |
+
# Predicted label and score of each query (batch_size, num_queries)
|
| 773 |
+
pred_scores, pred_labels = nn.functional.softmax(class_queries_logits, dim=-1).max(-1)
|
| 774 |
+
|
| 775 |
+
# Loop over items in batch size
|
| 776 |
+
results: list[dict[str, TensorType]] = []
|
| 777 |
+
|
| 778 |
+
for i in range(batch_size):
|
| 779 |
+
mask_probs_item, pred_scores_item, pred_labels_item = remove_low_and_no_objects(
|
| 780 |
+
mask_probs[i], pred_scores[i], pred_labels[i], threshold, num_labels
|
| 781 |
+
)
|
| 782 |
+
|
| 783 |
+
# No mask found
|
| 784 |
+
if mask_probs_item.shape[0] <= 0:
|
| 785 |
+
height, width = target_sizes[i] if target_sizes is not None else mask_probs_item.shape[1:]
|
| 786 |
+
segmentation = torch.zeros((height, width)) - 1
|
| 787 |
+
results.append({"segmentation": segmentation, "segments_info": []})
|
| 788 |
+
continue
|
| 789 |
+
|
| 790 |
+
# Get segmentation map and segment information of batch item
|
| 791 |
+
target_size = target_sizes[i] if target_sizes is not None else None
|
| 792 |
+
segmentation, segments = compute_segments(
|
| 793 |
+
mask_probs=mask_probs_item,
|
| 794 |
+
pred_scores=pred_scores_item,
|
| 795 |
+
pred_labels=pred_labels_item,
|
| 796 |
+
mask_threshold=mask_threshold,
|
| 797 |
+
overlap_mask_area_threshold=overlap_mask_area_threshold,
|
| 798 |
+
label_ids_to_fuse=label_ids_to_fuse,
|
| 799 |
+
target_size=target_size,
|
| 800 |
+
)
|
| 801 |
+
|
| 802 |
+
results.append({"segmentation": segmentation, "segments_info": segments})
|
| 803 |
+
return results
|
| 804 |
+
|
| 805 |
+
|
| 806 |
+
__all__ = ["MaskFormerImageProcessor"]
|