-
Notifications
You must be signed in to change notification settings - Fork 33.6k
Make pipeline able to load processor
#32514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 28 commits
a3465ce
e377b29
500098d
bab9a57
7fd209f
3db0e0b
71c2d5b
a010357
c526e08
d45d7f6
a95d556
94f5616
2bd4e0e
49ec283
5686833
0a2349e
7d507a6
3873c1c
92d2be8
01d6040
ab7a229
6e0dde8
4c834b3
6a8e590
0533995
e06053d
d553dab
6ff4e68
a6993b5
5799775
9793e01
e712717
bcce4dc
64f002c
cbb813f
6996695
b67d24f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -28,7 +28,9 @@ | |||
| from ..models.auto.feature_extraction_auto import FEATURE_EXTRACTOR_MAPPING, AutoFeatureExtractor | ||||
| from ..models.auto.image_processing_auto import IMAGE_PROCESSOR_MAPPING, AutoImageProcessor | ||||
| from ..models.auto.modeling_auto import AutoModelForDepthEstimation, AutoModelForImageToImage | ||||
| from ..models.auto.processing_auto import PROCESSOR_MAPPING, AutoProcessor | ||||
| from ..models.auto.tokenization_auto import TOKENIZER_MAPPING, AutoTokenizer | ||||
| from ..processing_utils import ProcessorMixin | ||||
| from ..tokenization_utils import PreTrainedTokenizer | ||||
| from ..utils import ( | ||||
| CONFIG_NAME, | ||||
|
|
@@ -556,6 +558,7 @@ def pipeline( | |||
| tokenizer: Optional[Union[str, PreTrainedTokenizer, "PreTrainedTokenizerFast"]] = None, | ||||
| feature_extractor: Optional[Union[str, PreTrainedFeatureExtractor]] = None, | ||||
| image_processor: Optional[Union[str, BaseImageProcessor]] = None, | ||||
| processor: Optional[Union[str, ProcessorMixin]] = None, | ||||
| framework: Optional[str] = None, | ||||
| revision: Optional[str] = None, | ||||
| use_fast: bool = True, | ||||
|
|
@@ -644,6 +647,25 @@ def pipeline( | |||
| `model` is not specified or not a string, then the default feature extractor for `config` is loaded (if it | ||||
| is a string). However, if `config` is also not given or not a string, then the default feature extractor | ||||
| for the given `task` will be loaded. | ||||
| image_procesor (`str` or [`BaseImageProcessor`], *optional*): | ||||
| The image processor that will be used by the pipeline to preprocess images for the model. This can be a | ||||
| model identifier or an actual image processor inheriting from [`BaseImageProcessor`]. | ||||
|
|
||||
| Image processors are used for Vision models and multi-modal models that require image inputs. Multi-modal | ||||
| models will also require a tokenizer to be passed. | ||||
|
|
||||
| If not provided, the default image processor for the given `model` will be loaded (if it is a string). If | ||||
| `model` is not specified or not a string, then the default image processor for `config` is loaded (if it is | ||||
| a string). | ||||
| processor (`str` or [`ProcessorMixin`], *optional*): | ||||
| The processor that will be used by the pipeline to preprocess data for the model. This can be a model | ||||
| identifier or an actual processor inheriting from [`ProcessorMixin`]. | ||||
|
|
||||
| Processors are used for multi-modal models that require multi-modal inputs, for example, a model that | ||||
| requires both text and image inputs. | ||||
|
|
||||
| If not provided, the default processor for the given `model` will be loaded (if it is a string). If `model` | ||||
| is not specified or not a string, then the default processor for `config` is loaded (if it is a string). | ||||
|
Comment on lines
+659
to
+676
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are now a few overlapping inputs:
I believe it would be nice to highlight somewhere visible (like in the documentation above) what attribute is necessary for what: at no point should a user specify all four of them, for example.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a separate For each specific pipeline we have only required processors args in docs section configured with docs decorator. e.g. here
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, updated pipeline doc to more relevant one in 6996695 |
||||
| framework (`str`, *optional*): | ||||
| The framework to use, either `"pt"` for PyTorch or `"tf"` for TensorFlow. The specified framework must be | ||||
| installed. | ||||
|
|
@@ -905,13 +927,17 @@ def pipeline( | |||
|
|
||||
| model_config = model.config | ||||
| hub_kwargs["_commit_hash"] = model.config._commit_hash | ||||
| load_tokenizer = ( | ||||
| type(model_config) in TOKENIZER_MAPPING | ||||
| or model_config.tokenizer_class is not None | ||||
| or isinstance(tokenizer, str) | ||||
| ) | ||||
|
|
||||
| load_tokenizer = type(model_config) in TOKENIZER_MAPPING or model_config.tokenizer_class is not None | ||||
| load_feature_extractor = type(model_config) in FEATURE_EXTRACTOR_MAPPING or feature_extractor is not None | ||||
| load_image_processor = type(model_config) in IMAGE_PROCESSOR_MAPPING or image_processor is not None | ||||
| load_processor = type(model_config) in PROCESSOR_MAPPING or processor is not None | ||||
|
|
||||
| # Check that pipeline class required loading | ||||
| load_tokenizer = load_tokenizer and pipeline_class._load_tokenizer | ||||
| load_feature_extractor = load_feature_extractor and pipeline_class._load_feature_extractor | ||||
| load_image_processor = load_image_processor and pipeline_class._load_image_processor | ||||
| load_processor = load_processor and pipeline_class._load_processor | ||||
|
Comment on lines
944
to
948
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For backward compatibility, we can control with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Piggy-backing on the comment above, this is likely something we want to highlight very clearly in each pipeline's documentation |
||||
|
|
||||
| # If `model` (instance of `PretrainedModel` instead of `str`) is passed (and/or same for config), while | ||||
| # `image_processor` or `feature_extractor` is `None`, the loading will fail. This happens particularly for some | ||||
|
|
@@ -1074,6 +1100,32 @@ def pipeline( | |||
| if not is_pyctcdecode_available(): | ||||
| logger.warning("Try to install `pyctcdecode`: `pip install pyctcdecode") | ||||
|
|
||||
| if load_processor: | ||||
| # Try to infer processor from model or config name (if provided as str) | ||||
| if processor is None: | ||||
| if isinstance(model_name, str): | ||||
| processor = model_name | ||||
| elif isinstance(config, str): | ||||
| processor = config | ||||
| else: | ||||
| # Impossible to guess what is the right processor here | ||||
| raise Exception( | ||||
| "Impossible to guess which processor to use. " | ||||
| "Please provide a processor instance or a path/identifier " | ||||
| "to a processor." | ||||
| ) | ||||
|
|
||||
| # Instantiate processor if needed | ||||
| if isinstance(processor, (str, tuple)): | ||||
| processor = AutoProcessor.from_pretrained(processor, _from_pipeline=task, **hub_kwargs, **model_kwargs) | ||||
| if not isinstance(processor, ProcessorMixin): | ||||
| warnings.warn( | ||||
| f"Processor will be not loaded, because {processor} is not an instance of `ProcessorMixin`. " | ||||
| f"Got type `{type(processor)}` instead.", | ||||
| UserWarning, | ||||
| ) | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With transformers already having too many warnings, I'd be cautious about the ones we add. What purpose does this warning serve? Is it sufficiently actionable? Does it concern users (the ones that will see it), or repo owners/creators that have not configured their processors/feature extractors correctly (that will likely not see this warning)?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the questions! Indeed, a misconfiguration in the model-pipeline-processor setup could trigger this and raising a warning + dropping the However, with granular control, such a case shouldn't occur. Therefore, it seems more appropriate to replace the warning with an error to clearly indicate a misconfiguration. Otherwise, the error will happen later with a less clear message because the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed to error raise here bcce4dc |
||||
| processor = None | ||||
|
|
||||
| if task == "translation" and model.config.task_specific_params: | ||||
| for key in model.config.task_specific_params: | ||||
| if key.startswith("translation"): | ||||
|
|
@@ -1099,4 +1151,7 @@ def pipeline( | |||
| if device is not None: | ||||
| kwargs["device"] = device | ||||
|
|
||||
| if processor is not None: | ||||
| kwargs["processor"] = processor | ||||
|
|
||||
| return pipeline_class(model=model, framework=framework, task=task, **kwargs) | ||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,7 @@ | |
| from ..image_processing_utils import BaseImageProcessor | ||
| from ..modelcard import ModelCard | ||
| from ..models.auto.configuration_auto import AutoConfig | ||
| from ..processing_utils import ProcessorMixin | ||
| from ..tokenization_utils import PreTrainedTokenizer | ||
| from ..utils import ( | ||
| ModelOutput, | ||
|
|
@@ -716,6 +717,7 @@ def build_pipeline_init_args( | |
| has_tokenizer: bool = False, | ||
| has_feature_extractor: bool = False, | ||
| has_image_processor: bool = False, | ||
| has_processor: bool = False, | ||
| supports_binary_output: bool = True, | ||
| ) -> str: | ||
| docstring = r""" | ||
|
|
@@ -738,6 +740,11 @@ def build_pipeline_init_args( | |
| image_processor ([`BaseImageProcessor`]): | ||
| The image processor that will be used by the pipeline to encode data for the model. This object inherits from | ||
| [`BaseImageProcessor`].""" | ||
| if has_processor: | ||
| docstring += r""" | ||
| processor ([`ProcessorMixin`]): | ||
| The processor that will be used by the pipeline to encode data for the model. This object inherits from | ||
| [`ProcessorMixin`].""" | ||
| docstring += r""" | ||
| modelcard (`str` or [`ModelCard`], *optional*): | ||
| Model card attributed to the model for this pipeline. | ||
|
|
@@ -774,7 +781,11 @@ def build_pipeline_init_args( | |
|
|
||
|
|
||
| PIPELINE_INIT_ARGS = build_pipeline_init_args( | ||
| has_tokenizer=True, has_feature_extractor=True, has_image_processor=True, supports_binary_output=True | ||
| has_tokenizer=True, | ||
| has_feature_extractor=True, | ||
| has_image_processor=True, | ||
| has_processor=True, | ||
| supports_binary_output=True, | ||
| ) | ||
|
|
||
|
|
||
|
|
@@ -805,6 +816,18 @@ class Pipeline(_ScikitCompat, PushToHubMixin): | |
| constructor argument. If set to `True`, the output will be stored in the pickle format. | ||
| """ | ||
|
|
||
| # Previously, pipelines support only `tokenizer`, `feature_extractor`, and `image_processor`. | ||
| # As we start adding `processor`, we want to avoid loading processor for some pipelines, that don't required it, | ||
|
qubvel marked this conversation as resolved.
Outdated
|
||
| # because, for example, use `image_processor` and `tokenizer` separately. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't get this comment 😁
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tried to make it clearer in 9793e01 |
||
| # However, we want to enable it for new pipelines. Moreover, this allow us to granularly control loading components | ||
| # and avoid loading tokenizer/image_processor/feature_extractor twice: once as a separate object | ||
| # and once in the processor. The following flags a set this way for backward compatibility ans might be overridden | ||
| # in specific Pipeline class. | ||
| _load_processor = False | ||
| _load_image_processor = True | ||
| _load_feature_extractor = True | ||
| _load_tokenizer = True | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. granular control for loading, see comment in the code
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this makes sense and I appreciate us being explicit. This repeats what is said above, but this should be extremely clear in the pipelines documentation if possible |
||
|
|
||
| default_input_names = None | ||
|
|
||
| def __init__( | ||
|
|
@@ -813,6 +836,7 @@ def __init__( | |
| tokenizer: Optional[PreTrainedTokenizer] = None, | ||
| feature_extractor: Optional[PreTrainedFeatureExtractor] = None, | ||
| image_processor: Optional[BaseImageProcessor] = None, | ||
| processor: Optional[ProcessorMixin] = None, | ||
| modelcard: Optional[ModelCard] = None, | ||
| framework: Optional[str] = None, | ||
| task: str = "", | ||
|
|
@@ -830,6 +854,7 @@ def __init__( | |
| self.tokenizer = tokenizer | ||
| self.feature_extractor = feature_extractor | ||
| self.image_processor = image_processor | ||
| self.processor = processor | ||
| self.modelcard = modelcard | ||
| self.framework = framework | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.