opsml.model.loader

  1# Copyright (c) Shipt, Inc.
  2# This source code is licensed under the MIT license found in the
  3# LICENSE file in the root directory of this source tree.
  4
  5# mypy: disable-error-code="arg-type"
  6
  7import json
  8from pathlib import Path
  9from typing import Any
 10
 11from opsml.model import HuggingFaceModel, ModelInterface
 12from opsml.types import ModelMetadata, OnnxModel, SaveName, Suffix
 13
 14
 15class ModelLoader:
 16    """Helper class for loading models from disk and downloading via opsml-cli"""
 17
 18    def __init__(self, path: Path):
 19        """Initialize ModelLoader
 20
 21        Args:
 22            interface:
 23                ModelInterface for the model
 24            path:
 25                Directory path to the model artifacts
 26        """
 27
 28        self.path = path
 29        self.metadata = self._load_metadata()
 30        self.interface = self._load_interface()
 31
 32    def _load_interface(self) -> ModelInterface:
 33        """Loads a ModelInterface from disk using metadata
 34
 35        Args:
 36            interface:
 37                ModelInterface to load
 38
 39        Returns:
 40            ModelInterface
 41        """
 42        from opsml.storage.card_loader import _get_model_interface
 43
 44        Interface = _get_model_interface(self.metadata.model_interface)  # pylint: disable=invalid-name
 45
 46        loaded_interface = Interface.model_construct(
 47            _fields_set={"name", "repository", "version"},
 48            **{
 49                "name": self.metadata.model_name,
 50                "repository": self.metadata.model_repository,
 51                "version": self.metadata.model_version,
 52            },
 53        )
 54
 55        loaded_interface.model_type = self.metadata.model_type
 56
 57        if hasattr(self.metadata, "prepocessor_name"):
 58            loaded_interface.preprocessor_name = self.metadata.preprocessor_name
 59
 60        if hasattr(self.metadata, "tokenizer_name"):
 61            loaded_interface.tokenizer_name = self.metadata.tokenizer_name
 62
 63        if hasattr(self.metadata, "feature_extractor_name"):
 64            loaded_interface.feature_extractor_name = self.metadata.feature_extractor_name
 65
 66        return loaded_interface
 67
 68    @property
 69    def model(self) -> Any:
 70        return self.interface.model
 71
 72    @property
 73    def onnx_model(self) -> OnnxModel:
 74        assert self.interface.onnx_model is not None, "OnnxModel not loaded"
 75        return self.interface.onnx_model
 76
 77    @property
 78    def preprocessor(self) -> Any:
 79        """Quick access to preprocessor from interface"""
 80
 81        if hasattr(self.interface, "preprocessor"):
 82            return self.interface.preprocessor
 83
 84        if hasattr(self.interface, "tokenizer"):
 85            if self.interface.tokenizer is not None:
 86                return self.interface.tokenizer
 87
 88        if hasattr(self.interface, "feature_extractor"):
 89            if self.interface.feature_extractor is not None:
 90                return self.interface.feature_extractor
 91
 92        return None
 93
 94    def _load_metadata(self) -> ModelMetadata:
 95        """Load metadata from disk"""
 96        metadata_path = (self.path / SaveName.MODEL_METADATA.value).with_suffix(Suffix.JSON.value)
 97
 98        with metadata_path.open("r") as file_:
 99            return ModelMetadata(**json.load(file_))
100
101    def _load_huggingface_preprocessors(self) -> None:
102        """Load huggingface preprocessors from disk"""
103
104        assert isinstance(self.interface, HuggingFaceModel), "HuggingFaceModel interface required"
105
106        if self.preprocessor is not None:
107            return
108
109        if hasattr(self.metadata, "tokenizer_name"):
110            load_path = (self.path / SaveName.TOKENIZER.value).with_suffix("")
111            self.interface.load_tokenizer(load_path)
112            return
113
114        if hasattr(self.metadata, "feature_extractor_name"):
115            load_path = (self.path / SaveName.FEATURE_EXTRACTOR.value).with_suffix("")
116            self.interface.load_feature_extractor(load_path)
117            return
118
119        return
120
121    def load_preprocessor(self) -> None:
122        """Load preprocessor from disk"""
123
124        if isinstance(self.interface, HuggingFaceModel):
125            self._load_huggingface_preprocessors()
126            return
127
128        if hasattr(self.metadata, "preprocessor_name"):
129            load_path = (self.path / SaveName.PREPROCESSOR.value).with_suffix(self.interface.preprocessor_suffix)
130            self.interface.load_preprocessor(load_path)
131            return
132
133        return
134
135    def load_model(self, **kwargs: Any) -> None:
136        load_path = (self.path / SaveName.TRAINED_MODEL.value).with_suffix(self.interface.model_suffix)
137        self.interface.load_model(load_path, **kwargs)
138
139        if isinstance(self.interface, HuggingFaceModel):
140            if self.interface.is_pipeline:
141                self.interface.to_pipeline()
142
143    def _load_huggingface_onnx_model(self, **kwargs: Any) -> None:
144        assert isinstance(self.interface, HuggingFaceModel), "Expected HuggingFaceModel"
145        load_quantized = kwargs.get("load_quantized", False)
146        save_name = SaveName.QUANTIZED_MODEL.value if load_quantized else SaveName.ONNX_MODEL.value
147
148        if self.interface.is_pipeline:
149            self._load_huggingface_preprocessors()
150
151        load_path = (self.path / save_name).with_suffix(self.interface.model_suffix)
152        self.interface.onnx_model = OnnxModel(onnx_version=self.metadata.onnx_version)
153        self.interface.load_onnx_model(load_path)
154
155    def load_onnx_model(self, **kwargs: Any) -> None:
156        """Load onnx model from disk
157
158        Kwargs:
159
160            ------Note: These kwargs only apply to HuggingFace models------
161
162            kwargs:
163                load_quantized:
164                    If True, load quantized model
165
166                onnx_args:
167                    Additional onnx args needed to load the model
168
169        """
170        if isinstance(self.interface, HuggingFaceModel):
171            self.interface.onnx_args = kwargs.get("onnx_args", None)
172            self._load_huggingface_onnx_model(**kwargs)
173            return
174
175        load_path = (self.path / SaveName.ONNX_MODEL.value).with_suffix(Suffix.ONNX.value)
176        self.interface.onnx_model = OnnxModel(onnx_version=self.metadata.onnx_version)
177        self.interface.load_onnx_model(load_path)
178        return
class ModelLoader:
 16class ModelLoader:
 17    """Helper class for loading models from disk and downloading via opsml-cli"""
 18
 19    def __init__(self, path: Path):
 20        """Initialize ModelLoader
 21
 22        Args:
 23            interface:
 24                ModelInterface for the model
 25            path:
 26                Directory path to the model artifacts
 27        """
 28
 29        self.path = path
 30        self.metadata = self._load_metadata()
 31        self.interface = self._load_interface()
 32
 33    def _load_interface(self) -> ModelInterface:
 34        """Loads a ModelInterface from disk using metadata
 35
 36        Args:
 37            interface:
 38                ModelInterface to load
 39
 40        Returns:
 41            ModelInterface
 42        """
 43        from opsml.storage.card_loader import _get_model_interface
 44
 45        Interface = _get_model_interface(self.metadata.model_interface)  # pylint: disable=invalid-name
 46
 47        loaded_interface = Interface.model_construct(
 48            _fields_set={"name", "repository", "version"},
 49            **{
 50                "name": self.metadata.model_name,
 51                "repository": self.metadata.model_repository,
 52                "version": self.metadata.model_version,
 53            },
 54        )
 55
 56        loaded_interface.model_type = self.metadata.model_type
 57
 58        if hasattr(self.metadata, "prepocessor_name"):
 59            loaded_interface.preprocessor_name = self.metadata.preprocessor_name
 60
 61        if hasattr(self.metadata, "tokenizer_name"):
 62            loaded_interface.tokenizer_name = self.metadata.tokenizer_name
 63
 64        if hasattr(self.metadata, "feature_extractor_name"):
 65            loaded_interface.feature_extractor_name = self.metadata.feature_extractor_name
 66
 67        return loaded_interface
 68
 69    @property
 70    def model(self) -> Any:
 71        return self.interface.model
 72
 73    @property
 74    def onnx_model(self) -> OnnxModel:
 75        assert self.interface.onnx_model is not None, "OnnxModel not loaded"
 76        return self.interface.onnx_model
 77
 78    @property
 79    def preprocessor(self) -> Any:
 80        """Quick access to preprocessor from interface"""
 81
 82        if hasattr(self.interface, "preprocessor"):
 83            return self.interface.preprocessor
 84
 85        if hasattr(self.interface, "tokenizer"):
 86            if self.interface.tokenizer is not None:
 87                return self.interface.tokenizer
 88
 89        if hasattr(self.interface, "feature_extractor"):
 90            if self.interface.feature_extractor is not None:
 91                return self.interface.feature_extractor
 92
 93        return None
 94
 95    def _load_metadata(self) -> ModelMetadata:
 96        """Load metadata from disk"""
 97        metadata_path = (self.path / SaveName.MODEL_METADATA.value).with_suffix(Suffix.JSON.value)
 98
 99        with metadata_path.open("r") as file_:
100            return ModelMetadata(**json.load(file_))
101
102    def _load_huggingface_preprocessors(self) -> None:
103        """Load huggingface preprocessors from disk"""
104
105        assert isinstance(self.interface, HuggingFaceModel), "HuggingFaceModel interface required"
106
107        if self.preprocessor is not None:
108            return
109
110        if hasattr(self.metadata, "tokenizer_name"):
111            load_path = (self.path / SaveName.TOKENIZER.value).with_suffix("")
112            self.interface.load_tokenizer(load_path)
113            return
114
115        if hasattr(self.metadata, "feature_extractor_name"):
116            load_path = (self.path / SaveName.FEATURE_EXTRACTOR.value).with_suffix("")
117            self.interface.load_feature_extractor(load_path)
118            return
119
120        return
121
122    def load_preprocessor(self) -> None:
123        """Load preprocessor from disk"""
124
125        if isinstance(self.interface, HuggingFaceModel):
126            self._load_huggingface_preprocessors()
127            return
128
129        if hasattr(self.metadata, "preprocessor_name"):
130            load_path = (self.path / SaveName.PREPROCESSOR.value).with_suffix(self.interface.preprocessor_suffix)
131            self.interface.load_preprocessor(load_path)
132            return
133
134        return
135
136    def load_model(self, **kwargs: Any) -> None:
137        load_path = (self.path / SaveName.TRAINED_MODEL.value).with_suffix(self.interface.model_suffix)
138        self.interface.load_model(load_path, **kwargs)
139
140        if isinstance(self.interface, HuggingFaceModel):
141            if self.interface.is_pipeline:
142                self.interface.to_pipeline()
143
144    def _load_huggingface_onnx_model(self, **kwargs: Any) -> None:
145        assert isinstance(self.interface, HuggingFaceModel), "Expected HuggingFaceModel"
146        load_quantized = kwargs.get("load_quantized", False)
147        save_name = SaveName.QUANTIZED_MODEL.value if load_quantized else SaveName.ONNX_MODEL.value
148
149        if self.interface.is_pipeline:
150            self._load_huggingface_preprocessors()
151
152        load_path = (self.path / save_name).with_suffix(self.interface.model_suffix)
153        self.interface.onnx_model = OnnxModel(onnx_version=self.metadata.onnx_version)
154        self.interface.load_onnx_model(load_path)
155
156    def load_onnx_model(self, **kwargs: Any) -> None:
157        """Load onnx model from disk
158
159        Kwargs:
160
161            ------Note: These kwargs only apply to HuggingFace models------
162
163            kwargs:
164                load_quantized:
165                    If True, load quantized model
166
167                onnx_args:
168                    Additional onnx args needed to load the model
169
170        """
171        if isinstance(self.interface, HuggingFaceModel):
172            self.interface.onnx_args = kwargs.get("onnx_args", None)
173            self._load_huggingface_onnx_model(**kwargs)
174            return
175
176        load_path = (self.path / SaveName.ONNX_MODEL.value).with_suffix(Suffix.ONNX.value)
177        self.interface.onnx_model = OnnxModel(onnx_version=self.metadata.onnx_version)
178        self.interface.load_onnx_model(load_path)
179        return

Helper class for loading models from disk and downloading via opsml-cli

ModelLoader(path: pathlib.Path)
19    def __init__(self, path: Path):
20        """Initialize ModelLoader
21
22        Args:
23            interface:
24                ModelInterface for the model
25            path:
26                Directory path to the model artifacts
27        """
28
29        self.path = path
30        self.metadata = self._load_metadata()
31        self.interface = self._load_interface()

Initialize ModelLoader

Arguments:
  • interface: ModelInterface for the model
  • path: Directory path to the model artifacts
path
metadata
interface
model: Any
69    @property
70    def model(self) -> Any:
71        return self.interface.model
onnx_model: opsml.types.model.OnnxModel
73    @property
74    def onnx_model(self) -> OnnxModel:
75        assert self.interface.onnx_model is not None, "OnnxModel not loaded"
76        return self.interface.onnx_model
preprocessor: Any
78    @property
79    def preprocessor(self) -> Any:
80        """Quick access to preprocessor from interface"""
81
82        if hasattr(self.interface, "preprocessor"):
83            return self.interface.preprocessor
84
85        if hasattr(self.interface, "tokenizer"):
86            if self.interface.tokenizer is not None:
87                return self.interface.tokenizer
88
89        if hasattr(self.interface, "feature_extractor"):
90            if self.interface.feature_extractor is not None:
91                return self.interface.feature_extractor
92
93        return None

Quick access to preprocessor from interface

def load_preprocessor(self) -> None:
122    def load_preprocessor(self) -> None:
123        """Load preprocessor from disk"""
124
125        if isinstance(self.interface, HuggingFaceModel):
126            self._load_huggingface_preprocessors()
127            return
128
129        if hasattr(self.metadata, "preprocessor_name"):
130            load_path = (self.path / SaveName.PREPROCESSOR.value).with_suffix(self.interface.preprocessor_suffix)
131            self.interface.load_preprocessor(load_path)
132            return
133
134        return

Load preprocessor from disk

def load_model(self, **kwargs: Any) -> None:
136    def load_model(self, **kwargs: Any) -> None:
137        load_path = (self.path / SaveName.TRAINED_MODEL.value).with_suffix(self.interface.model_suffix)
138        self.interface.load_model(load_path, **kwargs)
139
140        if isinstance(self.interface, HuggingFaceModel):
141            if self.interface.is_pipeline:
142                self.interface.to_pipeline()
def load_onnx_model(self, **kwargs: Any) -> None:
156    def load_onnx_model(self, **kwargs: Any) -> None:
157        """Load onnx model from disk
158
159        Kwargs:
160
161            ------Note: These kwargs only apply to HuggingFace models------
162
163            kwargs:
164                load_quantized:
165                    If True, load quantized model
166
167                onnx_args:
168                    Additional onnx args needed to load the model
169
170        """
171        if isinstance(self.interface, HuggingFaceModel):
172            self.interface.onnx_args = kwargs.get("onnx_args", None)
173            self._load_huggingface_onnx_model(**kwargs)
174            return
175
176        load_path = (self.path / SaveName.ONNX_MODEL.value).with_suffix(Suffix.ONNX.value)
177        self.interface.onnx_model = OnnxModel(onnx_version=self.metadata.onnx_version)
178        self.interface.load_onnx_model(load_path)
179        return

Load onnx model from disk

Kwargs:

------Note: These kwargs only apply to HuggingFace models------

kwargs: load_quantized: If True, load quantized model

onnx_args:
    Additional onnx args needed to load the model