DoruC/Grounded-Segment-Anything
0
1# coding=utf-82# Copyright 2022 The HuggingFace Inc. team.3#4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# 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 and14# limitations under the License.15"""16 Processing saving/loading class for common processors.17"""18 19import os20import warnings21from pathlib import Path22from typing import Optional, Union23 24from .dynamic_module_utils import custom_object_save25from .tokenization_utils_base import PreTrainedTokenizerBase26from .utils import PushToHubMixin, copy_func, direct_transformers_import, logging27 28 29logger = logging.get_logger(__name__)30 31# Dynamically import the Transformers module to grab the attribute classes of the processor form their names.32transformers_module = direct_transformers_import(Path(__file__).parent)33 34 35AUTO_TO_BASE_CLASS_MAPPING = {36 "AutoTokenizer": "PreTrainedTokenizerBase",37 "AutoFeatureExtractor": "FeatureExtractionMixin",38 "AutoImageProcessor": "ImageProcessingMixin",39}40 41 42class ProcessorMixin(PushToHubMixin):43 """44 This is a mixin used to provide saving/loading functionality for all processor classes.45 """46 47 attributes = ["feature_extractor", "tokenizer"]48 # Names need to be attr_class for attr in attributes49 feature_extractor_class = None50 tokenizer_class = None51 _auto_class = None52 53 # args have to match the attributes class attribute54 def __init__(self, *args, **kwargs):55 # Sanitize args and kwargs56 for key in kwargs:57 if key not in self.attributes:58 raise TypeError(f"Unexpected keyword argument {key}.")59 for arg, attribute_name in zip(args, self.attributes):60 if attribute_name in kwargs:61 raise TypeError(f"Got multiple values for argument {attribute_name}.")62 else:63 kwargs[attribute_name] = arg64 65 if len(kwargs) != len(self.attributes):66 raise ValueError(67 f"This processor requires {len(self.attributes)} arguments: {', '.join(self.attributes)}. Got "68 f"{len(args)} arguments instead."69 )70 71 # Check each arg is of the proper class (this will also catch a user initializing in the wrong order)72 for attribute_name, arg in kwargs.items():73 class_name = getattr(self, f"{attribute_name}_class")74 # Nothing is ever going to be an instance of "AutoXxx", in that case we check the base class.75 class_name = AUTO_TO_BASE_CLASS_MAPPING.get(class_name, class_name)76 if isinstance(class_name, tuple):77 proper_class = tuple(getattr(transformers_module, n) for n in class_name if n is not None)78 else:79 proper_class = getattr(transformers_module, class_name)80 81 if not isinstance(arg, proper_class):82 raise ValueError(83 f"Received a {type(arg).__name__} for argument {attribute_name}, but a {class_name} was expected."84 )85 86 setattr(self, attribute_name, arg)87 88 def __repr__(self):89 attributes_repr = [f"- {name}: {repr(getattr(self, name))}" for name in self.attributes]90 attributes_repr = "\n".join(attributes_repr)91 return f"{self.__class__.__name__}:\n{attributes_repr}"92 93 def save_pretrained(self, save_directory, push_to_hub: bool = False, **kwargs):94 """95 Saves the attributes of this processor (feature extractor, tokenizer...) in the specified directory so that it96 can be reloaded using the [`~ProcessorMixin.from_pretrained`] method.97 98 <Tip>99 100 This class method is simply calling [`~feature_extraction_utils.FeatureExtractionMixin.save_pretrained`] and101 [`~tokenization_utils_base.PreTrainedTokenizerBase.save_pretrained`]. Please refer to the docstrings of the102 methods above for more information.103 104 </Tip>105 106 Args:107 save_directory (`str` or `os.PathLike`):108 Directory where the feature extractor JSON file and the tokenizer files will be saved (directory will109 be created if it does not exist).110 push_to_hub (`bool`, *optional*, defaults to `False`):111 Whether or not to push your model to the Hugging Face model hub after saving it. You can specify the112 repository you want to push to with `repo_id` (will default to the name of `save_directory` in your113 namespace).114 kwargs (`Dict[str, Any]`, *optional*):115 Additional key word arguments passed along to the [`~utils.PushToHubMixin.push_to_hub`] method.116 """117 use_auth_token = kwargs.pop("use_auth_token", None)118 119 if use_auth_token is not None:120 warnings.warn(121 "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers.", FutureWarning122 )123 if kwargs.get("token", None) is not None:124 raise ValueError(125 "`token` and `use_auth_token` are both specified. Please set only the argument `token`."126 )127 kwargs["token"] = use_auth_token128 129 os.makedirs(save_directory, exist_ok=True)130 131 if push_to_hub:132 commit_message = kwargs.pop("commit_message", None)133 repo_id = kwargs.pop("repo_id", save_directory.split(os.path.sep)[-1])134 repo_id = self._create_repo(repo_id, **kwargs)135 files_timestamps = self._get_files_timestamps(save_directory)136 # If we have a custom config, we copy the file defining it in the folder and set the attributes so it can be137 # loaded from the Hub.138 if self._auto_class is not None:139 attrs = [getattr(self, attribute_name) for attribute_name in self.attributes]140 configs = [(a.init_kwargs if isinstance(a, PreTrainedTokenizerBase) else a) for a in attrs]141 custom_object_save(self, save_directory, config=configs)142 143 for attribute_name in self.attributes:144 attribute = getattr(self, attribute_name)145 # Include the processor class in the attribute config so this processor can then be reloaded with the146 # `AutoProcessor` API.147 if hasattr(attribute, "_set_processor_class"):148 attribute._set_processor_class(self.__class__.__name__)149 attribute.save_pretrained(save_directory)150 151 if self._auto_class is not None:152 # We added an attribute to the init_kwargs of the tokenizers, which needs to be cleaned up.153 for attribute_name in self.attributes:154 attribute = getattr(self, attribute_name)155 if isinstance(attribute, PreTrainedTokenizerBase):156 del attribute.init_kwargs["auto_map"]157 158 if push_to_hub:159 self._upload_modified_files(160 save_directory,161 repo_id,162 files_timestamps,163 commit_message=commit_message,164 token=kwargs.get("token"),165 )166 167 @classmethod168 def from_pretrained(169 cls,170 pretrained_model_name_or_path: Union[str, os.PathLike],171 cache_dir: Optional[Union[str, os.PathLike]] = None,172 force_download: bool = False,173 local_files_only: bool = False,174 token: Optional[Union[str, bool]] = None,175 revision: str = "main",176 **kwargs,177 ):178 r"""179 Instantiate a processor associated with a pretrained model.180 181 <Tip>182 183 This class method is simply calling the feature extractor184 [`~feature_extraction_utils.FeatureExtractionMixin.from_pretrained`], image processor185 [`~image_processing_utils.ImageProcessingMixin`] and the tokenizer186 [`~tokenization_utils_base.PreTrainedTokenizer.from_pretrained`] methods. Please refer to the docstrings of the187 methods above for more information.188 189 </Tip>190 191 Args:192 pretrained_model_name_or_path (`str` or `os.PathLike`):193 This can be either:194 195 - a string, the *model id* of a pretrained feature_extractor hosted inside a model repo on196 huggingface.co. Valid model ids can be located at the root-level, like `bert-base-uncased`, or197 namespaced under a user or organization name, like `dbmdz/bert-base-german-cased`.198 - a path to a *directory* containing a feature extractor file saved using the199 [`~SequenceFeatureExtractor.save_pretrained`] method, e.g., `./my_model_directory/`.200 - a path or url to a saved feature extractor JSON *file*, e.g.,201 `./my_model_directory/preprocessor_config.json`.202 **kwargs203 Additional keyword arguments passed along to both204 [`~feature_extraction_utils.FeatureExtractionMixin.from_pretrained`] and205 [`~tokenization_utils_base.PreTrainedTokenizer.from_pretrained`].206 """207 kwargs["cache_dir"] = cache_dir208 kwargs["force_download"] = force_download209 kwargs["local_files_only"] = local_files_only210 kwargs["revision"] = revision211 212 use_auth_token = kwargs.pop("use_auth_token", None)213 if use_auth_token is not None:214 warnings.warn(215 "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers.", FutureWarning216 )217 if token is not None:218 raise ValueError(219 "`token` and `use_auth_token` are both specified. Please set only the argument `token`."220 )221 token = use_auth_token222 223 if token is not None:224 kwargs["token"] = token225 226 args = cls._get_arguments_from_pretrained(pretrained_model_name_or_path, **kwargs)227 return cls(*args)228 229 @classmethod230 def register_for_auto_class(cls, auto_class="AutoProcessor"):231 """232 Register this class with a given auto class. This should only be used for custom feature extractors as the ones233 in the library are already mapped with `AutoProcessor`.234 235 <Tip warning={true}>236 237 This API is experimental and may have some slight breaking changes in the next releases.238 239 </Tip>240 241 Args:242 auto_class (`str` or `type`, *optional*, defaults to `"AutoProcessor"`):243 The auto class to register this new feature extractor with.244 """245 if not isinstance(auto_class, str):246 auto_class = auto_class.__name__247 248 import transformers.models.auto as auto_module249 250 if not hasattr(auto_module, auto_class):251 raise ValueError(f"{auto_class} is not a valid auto class.")252 253 cls._auto_class = auto_class254 255 @classmethod256 def _get_arguments_from_pretrained(cls, pretrained_model_name_or_path, **kwargs):257 args = []258 for attribute_name in cls.attributes:259 class_name = getattr(cls, f"{attribute_name}_class")260 if isinstance(class_name, tuple):261 classes = tuple(getattr(transformers_module, n) if n is not None else None for n in class_name)262 use_fast = kwargs.get("use_fast", True)263 if use_fast and classes[1] is not None:264 attribute_class = classes[1]265 else:266 attribute_class = classes[0]267 else:268 attribute_class = getattr(transformers_module, class_name)269 270 args.append(attribute_class.from_pretrained(pretrained_model_name_or_path, **kwargs))271 return args272 273 @property274 def model_input_names(self):275 first_attribute = getattr(self, self.attributes[0])276 return getattr(first_attribute, "model_input_names", None)277 278 279ProcessorMixin.push_to_hub = copy_func(ProcessorMixin.push_to_hub)280if ProcessorMixin.push_to_hub.__doc__ is not None:281 ProcessorMixin.push_to_hub.__doc__ = ProcessorMixin.push_to_hub.__doc__.format(282 object="processor", object_class="AutoProcessor", object_files="processor files"283 )284 