194 lines
8.4 KiB
Python
194 lines
8.4 KiB
Python
# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
|
|
# Copyright 2018 Google AI, Google Brain and the HuggingFace Inc. team.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import importlib
|
|
import io
|
|
import json
|
|
import os
|
|
from collections import OrderedDict
|
|
|
|
from ...utils.download import resolve_file_path
|
|
from ...utils.import_utils import import_module
|
|
from ...utils.log import logger
|
|
|
|
__all__ = [
|
|
"AutoProcessor",
|
|
]
|
|
|
|
PROCESSOR_MAPPING_NAMES = OrderedDict(
|
|
[
|
|
("ChineseCLIPProcessor", "chineseclip"),
|
|
("CLIPProcessor", "clip"),
|
|
("ErnieViLProcessor", "ernie_vil"),
|
|
("CLIPSegProcessor", "clipseg"),
|
|
("SpeechT5Processor", "speecht5"),
|
|
("ClapProcessor", "clap"),
|
|
]
|
|
)
|
|
|
|
|
|
def get_configurations():
|
|
MAPPING_NAMES = OrderedDict()
|
|
for key, class_name in PROCESSOR_MAPPING_NAMES.items():
|
|
import_class = importlib.import_module(f"paddlenlp.transformers.{class_name}.processing")
|
|
processor_name = getattr(import_class, key)
|
|
name = tuple(processor_name.pretrained_init_configuration.keys())
|
|
if MAPPING_NAMES.get(name, None) is None:
|
|
MAPPING_NAMES[name] = []
|
|
MAPPING_NAMES[name].append(processor_name)
|
|
return MAPPING_NAMES
|
|
|
|
|
|
class AutoProcessor:
|
|
"""
|
|
AutoClass can help you automatically retrieve the relevant model given the provided
|
|
pretrained weights/vocabulary.
|
|
Autoprocessor is a generic processor class that will be instantiated as one of the
|
|
base processor classes when created with the Autoprocessor.from_pretrained() classmethod.
|
|
"""
|
|
|
|
MAPPING_NAMES = get_configurations()
|
|
_processor_mapping = MAPPING_NAMES
|
|
_name_mapping = PROCESSOR_MAPPING_NAMES
|
|
processor_config_file = "preprocessor_config.json"
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
raise EnvironmentError(
|
|
f"{self.__class__.__name__} is designed to be instantiated "
|
|
f"using the `{self.__class__.__name__}.from_pretrained(pretrained_model_name_or_path).`"
|
|
)
|
|
|
|
@classmethod
|
|
def _get_processor_class_from_config(cls, pretrained_model_name_or_path, config_file_path):
|
|
with io.open(config_file_path, encoding="utf-8") as f:
|
|
init_kwargs = json.load(f)
|
|
# class name corresponds to this configuration
|
|
init_class = init_kwargs.pop("init_class", None)
|
|
if init_class is None:
|
|
init_class = init_kwargs.pop("processor_class", None)
|
|
if init_class is None:
|
|
init_class = init_kwargs.pop("image_processor_type", None)
|
|
# replace old name to new name
|
|
if init_class is not None and init_class.endswith("ImageProcessor"):
|
|
init_class = init_class.replace("ImageProcessor", "Processor")
|
|
if init_class is None:
|
|
init_class = init_kwargs.pop("feature_extractor_type", None)
|
|
# replace old name to new name
|
|
if init_class is not None and init_class.endswith("FeatureExtractor"):
|
|
init_class = init_class.replace("FeatureExtractor", "Processor")
|
|
|
|
if init_class:
|
|
try:
|
|
class_name = cls._name_mapping[init_class]
|
|
import_class = import_module(f"paddlenlp.transformers.{class_name}.processing")
|
|
processor_class = getattr(import_class, init_class)
|
|
return processor_class
|
|
except Exception:
|
|
init_class = None
|
|
|
|
# If no `init_class`, we use pattern recognition to recognize the processor class.
|
|
if init_class is None:
|
|
logger.info("We use pattern recognition to recognize the processor class.")
|
|
for key, pattern in cls._name_mapping.items():
|
|
if pattern in pretrained_model_name_or_path.lower():
|
|
init_class = key
|
|
class_name = cls._name_mapping[init_class]
|
|
import_class = import_module(f"paddlenlp.transformers.{class_name}.processor")
|
|
processor_class = getattr(import_class, init_class)
|
|
break
|
|
return processor_class
|
|
|
|
@classmethod
|
|
def from_pretrained(cls, pretrained_model_name_or_path, *model_args, **kwargs):
|
|
"""
|
|
Creates an instance of `Autoprocessor`. Related resources are loaded by
|
|
specifying name of a built-in pretrained model, or a community-contributed
|
|
pretrained model, or a local file directory path.
|
|
|
|
Args:
|
|
pretrained_model_name_or_path (str): Name of pretrained model or dir path
|
|
to load from. The string can be:
|
|
|
|
- Name of built-in pretrained model
|
|
- Name of a community-contributed pretrained model.
|
|
- Local directory path which contains processor related resources
|
|
and processor config file ("processor_config.json").
|
|
*args (tuple): position arguments for model `__init__`. If provided,
|
|
use these as position argument values for processor initialization.
|
|
**kwargs (dict): keyword arguments for model `__init__`. If provided,
|
|
use these to update pre-defined keyword argument values for processor
|
|
initialization.
|
|
|
|
Returns:
|
|
Pretrainedprocessor: An instance of `Pretrainedprocessor`.
|
|
|
|
|
|
Example:
|
|
.. code-block::
|
|
from paddlenlp.transformers import AutoProcessor
|
|
processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
|
processor.save_pretrained('clip_processor')
|
|
"""
|
|
cache_dir = kwargs.get("cache_dir", None)
|
|
subfolder = kwargs.get("subfolder", "")
|
|
if subfolder is None:
|
|
subfolder = ""
|
|
from_aistudio = kwargs.get("from_aistudio", False)
|
|
from_hf_hub = kwargs.get("from_hf_hub", False)
|
|
kwargs["subfolder"] = subfolder
|
|
kwargs["cache_dir"] = cache_dir
|
|
|
|
all_processor_names = []
|
|
for names, processor_class in cls._processor_mapping.items():
|
|
for name in names:
|
|
all_processor_names.append(name)
|
|
|
|
# From built-in pretrained models
|
|
if pretrained_model_name_or_path in all_processor_names:
|
|
for names, processor_classes in cls._processor_mapping.items():
|
|
for pattern in names:
|
|
if pattern == pretrained_model_name_or_path:
|
|
actual_processor_class = processor_classes[0]
|
|
logger.info(
|
|
"We are using %s to load '%s'." % (actual_processor_class, pretrained_model_name_or_path)
|
|
)
|
|
return actual_processor_class.from_pretrained(
|
|
pretrained_model_name_or_path, *model_args, **kwargs
|
|
)
|
|
|
|
config_file = resolve_file_path(
|
|
pretrained_model_name_or_path,
|
|
[cls.processor_config_file],
|
|
subfolder,
|
|
cache_dir=cache_dir,
|
|
from_hf_hub=from_hf_hub,
|
|
from_aistudio=from_aistudio,
|
|
)
|
|
if config_file is not None and os.path.exists(config_file):
|
|
processor_class = cls._get_processor_class_from_config(
|
|
pretrained_model_name_or_path,
|
|
config_file,
|
|
)
|
|
logger.info(f"We are using {processor_class} to load '{pretrained_model_name_or_path}'.")
|
|
return processor_class.from_pretrained(pretrained_model_name_or_path, *model_args, **kwargs)
|
|
else:
|
|
raise RuntimeError(
|
|
f"Can't load processor for '{pretrained_model_name_or_path}'.\n"
|
|
f"Please make sure that '{pretrained_model_name_or_path}' is:\n"
|
|
"- a correct model-identifier of built-in pretrained processor,\n"
|
|
"- or a correct model-identifier of community-contributed pretrained models,\n"
|
|
"- or the correct path to a directory containing relevant processor files.\n"
|
|
)
|