bikes.io.registries
Savers, loaders, and registers for model registries.
1"""Savers, loaders, and registers for model registries.""" 2 3# %% IMPORTS 4 5import abc 6import tempfile 7import typing as T 8from pathlib import Path 9 10import mlflow 11import pandas as pd 12import pydantic as pdt 13from mlflow.pyfunc import PyFuncModel, PythonModel, PythonModelContext 14 15from bikes.core import models, schemas 16from bikes.utils import signers 17 18# %% TYPES 19 20# Results of model registry operations 21Info: T.TypeAlias = mlflow.models.model.ModelInfo 22Alias: T.TypeAlias = mlflow.entities.model_registry.ModelVersion 23Version: T.TypeAlias = mlflow.entities.model_registry.ModelVersion 24 25# %% HELPERS 26 27 28def uri_for_model_alias(name: str, alias: str) -> str: 29 """Create a model URI from a model name and an alias. 30 31 Args: 32 name (str): name of the mlflow registered model. 33 alias (str): alias of the registered model. 34 35 Returns: 36 str: model URI as "models:/name@alias". 37 """ 38 return f"models:/{name}@{alias}" 39 40 41def uri_for_model_version(name: str, version: int) -> str: 42 """Create a model URI from a model name and a version. 43 44 Args: 45 name (str): name of the mlflow registered model. 46 version (int): version of the registered model. 47 48 Returns: 49 str: model URI as "models:/name/version." 50 """ 51 return f"models:/{name}/{version}" 52 53 54def uri_for_model_alias_or_version(name: str, alias_or_version: str | int) -> str: 55 """Create a model URi from a model name and an alias or version. 56 57 Args: 58 name (str): name of the mlflow registered model. 59 alias_or_version (str | int): alias or version of the registered model. 60 61 Returns: 62 str: model URI as "models:/name@alias" or "models:/name/version" based on input. 63 """ 64 if isinstance(alias_or_version, int): 65 return uri_for_model_version(name=name, version=alias_or_version) 66 return uri_for_model_alias(name=name, alias=alias_or_version) 67 68 69# %% SAVERS 70 71 72class Saver(abc.ABC, pdt.BaseModel, strict=True, frozen=True, extra="forbid"): 73 """Base class for saving models in registry. 74 75 Separate model definition from serialization. 76 e.g., to switch between serialization flavors. 77 78 Parameters: 79 path (str): model path inside the Mlflow store. 80 """ 81 82 KIND: str 83 84 path: str = "model" 85 86 @abc.abstractmethod 87 def save( 88 self, 89 model: models.Model, 90 signature: signers.Signature, 91 input_example: schemas.Inputs, 92 ) -> Info: 93 """Save a model in the model registry. 94 95 Args: 96 model (models.Model): project model to save. 97 signature (signers.Signature): model signature. 98 input_example (schemas.Inputs): sample of inputs. 99 100 Returns: 101 Info: model saving information. 102 """ 103 104 105class CustomSaver(Saver): 106 """Saver for project models using the Mlflow PyFunc module. 107 108 Nothing is pickled: the adapter is logged as code (MLflow "models from code"), the 109 model params as its `model_config`, and the fitted internal model as a skops file. 110 111 https://mlflow.org/docs/latest/ml/model/models-from-code/ 112 """ 113 114 KIND: T.Literal["CustomSaver"] = "CustomSaver" 115 116 # Code file that MLflow copies with the model and runs to rebuild the adapter. 117 CODE: T.ClassVar[Path] = Path(__file__).with_name("pyfunc_model.py") 118 119 class Adapter(PythonModel): # type: ignore[misc] 120 """Adapt a custom model to the Mlflow PyFunc flavor. 121 122 https://mlflow.org/docs/latest/python_api/mlflow.pyfunc.html?#mlflow.pyfunc.PythonModel 123 """ 124 125 model: models.Model 126 127 def load_context(self, context: PythonModelContext) -> None: 128 """Rebuild the project model from its params and its internal model file. 129 130 Args: 131 context (mlflow.PythonModelContext): mlflow context with config and artifacts. 132 """ 133 model = pdt.TypeAdapter(models.ModelKind).validate_python(context.model_config) 134 self.model = model.load_internal_model(path=context.artifacts["model"]) 135 136 def predict( 137 self, 138 context: PythonModelContext, # noqa: ARG002 # required by mlflow PythonModel.predict 139 model_input: pd.DataFrame, 140 params: dict[str, T.Any] | None = None, # noqa: ARG002 # required by mlflow PythonModel.predict 141 ) -> schemas.Outputs: 142 """Generate predictions with a custom model for the given inputs. 143 144 Args: 145 context (mlflow.PythonModelContext): mlflow context. 146 model_input (pd.DataFrame): inputs to validate for the mlflow model. 147 params (dict[str, T.Any] | None): additional parameters. 148 149 Returns: 150 schemas.Outputs: validated outputs of the project model. 151 """ 152 # MLflow accepts pandas here and validates the logged signature; 153 # Pandera enforces the project's constraints before the typed model call. 154 inputs = schemas.InputsSchema.check(data=model_input) 155 return self.model.predict(inputs=inputs) 156 157 @T.override 158 def save( 159 self, 160 model: models.Model, 161 signature: signers.Signature, 162 input_example: schemas.Inputs, 163 ) -> Info: 164 with tempfile.TemporaryDirectory() as directory: 165 path = Path(directory) / "model.skops" 166 model.save_internal_model(path=str(path)) 167 return mlflow.pyfunc.log_model( 168 name=self.path, 169 python_model=str(self.CODE), 170 artifacts={"model": str(path)}, 171 model_config=model.model_dump(), 172 signature=signature, 173 input_example=input_example, 174 ) 175 176 177class BuiltinSaver(Saver): 178 """Saver for built-in models using an Mlflow flavor module. 179 180 https://mlflow.org/docs/latest/models.html#built-in-model-flavors 181 182 Parameters: 183 flavor (str): Mlflow flavor module to use for the serialization. 184 kwargs (dict[str, T.Any]): flavor-specific options for `log_model`. 185 e.g., sklearn saves with skops, which refuses to reload tree models 186 unless their types are trusted: `{"skops_trusted_types": [...]}`. 187 """ 188 189 KIND: T.Literal["BuiltinSaver"] = "BuiltinSaver" 190 191 flavor: str 192 kwargs: dict[str, T.Any] = {} 193 194 @T.override 195 def save( 196 self, 197 model: models.Model, 198 signature: signers.Signature, 199 input_example: schemas.Inputs, 200 ) -> Info: 201 builtin_model = model.get_internal_model() 202 module = getattr(mlflow, self.flavor) 203 return module.log_model( 204 builtin_model, 205 name=self.path, 206 signature=signature, 207 input_example=input_example, 208 **self.kwargs, 209 ) 210 211 212SaverKind = CustomSaver | BuiltinSaver 213 214# %% LOADERS 215 216 217class Loader(abc.ABC, pdt.BaseModel, strict=True, frozen=True, extra="forbid"): 218 """Base class for loading models from registry. 219 220 Separate model definition from deserialization. 221 e.g., to switch between deserialization flavors. 222 """ 223 224 KIND: str 225 226 class Adapter(abc.ABC): 227 """Adapt any model for the project inference.""" 228 229 @abc.abstractmethod 230 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 231 """Generate predictions with the internal model for the given inputs. 232 233 Args: 234 inputs (schemas.Inputs): validated inputs for the project model. 235 236 Returns: 237 schemas.Outputs: validated outputs of the project model. 238 """ 239 240 @abc.abstractmethod 241 def load(self, uri: str) -> Loader.Adapter: 242 """Load a model from the model registry. 243 244 Args: 245 uri (str): URI of a model to load. 246 247 Returns: 248 Loader.Adapter: model loaded. 249 """ 250 251 252class CustomLoader(Loader): 253 """Loader for custom models using the Mlflow PyFunc module. 254 255 https://mlflow.org/docs/latest/python_api/mlflow.pyfunc.html 256 """ 257 258 KIND: T.Literal["CustomLoader"] = "CustomLoader" 259 260 class Adapter(Loader.Adapter): 261 """Adapt a custom model for the project inference.""" 262 263 def __init__(self, model: PyFuncModel) -> None: 264 """Initialize the adapter from an mlflow pyfunc model. 265 266 Args: 267 model (PyFuncModel): mlflow pyfunc model. 268 """ 269 self.model = model 270 271 @T.override 272 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 273 # model validation is already done in predict 274 outputs = self.model.predict(data=inputs) 275 return T.cast(schemas.Outputs, outputs) 276 277 @T.override 278 def load(self, uri: str) -> CustomLoader.Adapter: 279 model = mlflow.pyfunc.load_model(model_uri=uri) 280 return CustomLoader.Adapter(model=model) 281 282 283class BuiltinLoader(Loader): 284 """Loader for built-in models using the Mlflow PyFunc module. 285 286 Note: use Mlflow PyFunc instead of flavors to use standard API. 287 288 https://mlflow.org/docs/latest/models.html#built-in-model-flavors 289 """ 290 291 KIND: T.Literal["BuiltinLoader"] = "BuiltinLoader" 292 293 class Adapter(Loader.Adapter): 294 """Adapt a builtin model for the project inference.""" 295 296 def __init__(self, model: PyFuncModel) -> None: 297 """Initialize the adapter from an mlflow pyfunc model. 298 299 Args: 300 model (PyFuncModel): mlflow pyfunc model. 301 """ 302 self.model = model 303 304 @T.override 305 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 306 columns = list(schemas.OutputsSchema.to_schema().columns) 307 outputs = self.model.predict(data=inputs) # unchecked data! 308 return schemas.Outputs(outputs, columns=columns, index=inputs.index) 309 310 @T.override 311 def load(self, uri: str) -> BuiltinLoader.Adapter: 312 model = mlflow.pyfunc.load_model(model_uri=uri) 313 return BuiltinLoader.Adapter(model=model) 314 315 316LoaderKind = CustomLoader | BuiltinLoader 317 318# %% REGISTERS 319 320 321class Register(abc.ABC, pdt.BaseModel, strict=True, frozen=True, extra="forbid"): 322 """Base class for registring models to a location. 323 324 Separate model definition from its registration. 325 e.g., to change the model registry backend. 326 327 Parameters: 328 tags (dict[str, T.Any]): tags for the model. 329 """ 330 331 KIND: str 332 333 tags: dict[str, T.Any] = {} 334 335 @abc.abstractmethod 336 def register(self, name: str, model_uri: str) -> Version: 337 """Register a model given its name and URI. 338 339 Args: 340 name (str): name of the model to register. 341 model_uri (str): URI of a model to register. 342 343 Returns: 344 Version: information about the registered model. 345 """ 346 347 348class MlflowRegister(Register): 349 """Register for models in the Mlflow Model Registry. 350 351 https://mlflow.org/docs/latest/model-registry.html 352 """ 353 354 KIND: T.Literal["MlflowRegister"] = "MlflowRegister" 355 356 @T.override 357 def register(self, name: str, model_uri: str) -> Version: 358 return mlflow.register_model(name=name, model_uri=model_uri, tags=self.tags) 359 360 361RegisterKind = MlflowRegister
29def uri_for_model_alias(name: str, alias: str) -> str: 30 """Create a model URI from a model name and an alias. 31 32 Args: 33 name (str): name of the mlflow registered model. 34 alias (str): alias of the registered model. 35 36 Returns: 37 str: model URI as "models:/name@alias". 38 """ 39 return f"models:/{name}@{alias}"
Create a model URI from a model name and an alias.
Arguments:
- name (str): name of the mlflow registered model.
- alias (str): alias of the registered model.
Returns:
str: model URI as "models:/name@alias".
42def uri_for_model_version(name: str, version: int) -> str: 43 """Create a model URI from a model name and a version. 44 45 Args: 46 name (str): name of the mlflow registered model. 47 version (int): version of the registered model. 48 49 Returns: 50 str: model URI as "models:/name/version." 51 """ 52 return f"models:/{name}/{version}"
Create a model URI from a model name and a version.
Arguments:
- name (str): name of the mlflow registered model.
- version (int): version of the registered model.
Returns:
str: model URI as "models:/name/version."
55def uri_for_model_alias_or_version(name: str, alias_or_version: str | int) -> str: 56 """Create a model URi from a model name and an alias or version. 57 58 Args: 59 name (str): name of the mlflow registered model. 60 alias_or_version (str | int): alias or version of the registered model. 61 62 Returns: 63 str: model URI as "models:/name@alias" or "models:/name/version" based on input. 64 """ 65 if isinstance(alias_or_version, int): 66 return uri_for_model_version(name=name, version=alias_or_version) 67 return uri_for_model_alias(name=name, alias=alias_or_version)
Create a model URi from a model name and an alias or version.
Arguments:
- name (str): name of the mlflow registered model.
- alias_or_version (str | int): alias or version of the registered model.
Returns:
str: model URI as "models:/name@alias" or "models:/name/version" based on input.
73class Saver(abc.ABC, pdt.BaseModel, strict=True, frozen=True, extra="forbid"): 74 """Base class for saving models in registry. 75 76 Separate model definition from serialization. 77 e.g., to switch between serialization flavors. 78 79 Parameters: 80 path (str): model path inside the Mlflow store. 81 """ 82 83 KIND: str 84 85 path: str = "model" 86 87 @abc.abstractmethod 88 def save( 89 self, 90 model: models.Model, 91 signature: signers.Signature, 92 input_example: schemas.Inputs, 93 ) -> Info: 94 """Save a model in the model registry. 95 96 Args: 97 model (models.Model): project model to save. 98 signature (signers.Signature): model signature. 99 input_example (schemas.Inputs): sample of inputs. 100 101 Returns: 102 Info: model saving information. 103 """
Base class for saving models in registry.
Separate model definition from serialization. e.g., to switch between serialization flavors.
Arguments:
- path (str): model path inside the Mlflow store.
87 @abc.abstractmethod 88 def save( 89 self, 90 model: models.Model, 91 signature: signers.Signature, 92 input_example: schemas.Inputs, 93 ) -> Info: 94 """Save a model in the model registry. 95 96 Args: 97 model (models.Model): project model to save. 98 signature (signers.Signature): model signature. 99 input_example (schemas.Inputs): sample of inputs. 100 101 Returns: 102 Info: model saving information. 103 """
Save a model in the model registry.
Arguments:
- model (models.Model): project model to save.
- signature (signers.Signature): model signature.
- input_example (schemas.Inputs): sample of inputs.
Returns:
Info: model saving information.
106class CustomSaver(Saver): 107 """Saver for project models using the Mlflow PyFunc module. 108 109 Nothing is pickled: the adapter is logged as code (MLflow "models from code"), the 110 model params as its `model_config`, and the fitted internal model as a skops file. 111 112 https://mlflow.org/docs/latest/ml/model/models-from-code/ 113 """ 114 115 KIND: T.Literal["CustomSaver"] = "CustomSaver" 116 117 # Code file that MLflow copies with the model and runs to rebuild the adapter. 118 CODE: T.ClassVar[Path] = Path(__file__).with_name("pyfunc_model.py") 119 120 class Adapter(PythonModel): # type: ignore[misc] 121 """Adapt a custom model to the Mlflow PyFunc flavor. 122 123 https://mlflow.org/docs/latest/python_api/mlflow.pyfunc.html?#mlflow.pyfunc.PythonModel 124 """ 125 126 model: models.Model 127 128 def load_context(self, context: PythonModelContext) -> None: 129 """Rebuild the project model from its params and its internal model file. 130 131 Args: 132 context (mlflow.PythonModelContext): mlflow context with config and artifacts. 133 """ 134 model = pdt.TypeAdapter(models.ModelKind).validate_python(context.model_config) 135 self.model = model.load_internal_model(path=context.artifacts["model"]) 136 137 def predict( 138 self, 139 context: PythonModelContext, # noqa: ARG002 # required by mlflow PythonModel.predict 140 model_input: pd.DataFrame, 141 params: dict[str, T.Any] | None = None, # noqa: ARG002 # required by mlflow PythonModel.predict 142 ) -> schemas.Outputs: 143 """Generate predictions with a custom model for the given inputs. 144 145 Args: 146 context (mlflow.PythonModelContext): mlflow context. 147 model_input (pd.DataFrame): inputs to validate for the mlflow model. 148 params (dict[str, T.Any] | None): additional parameters. 149 150 Returns: 151 schemas.Outputs: validated outputs of the project model. 152 """ 153 # MLflow accepts pandas here and validates the logged signature; 154 # Pandera enforces the project's constraints before the typed model call. 155 inputs = schemas.InputsSchema.check(data=model_input) 156 return self.model.predict(inputs=inputs) 157 158 @T.override 159 def save( 160 self, 161 model: models.Model, 162 signature: signers.Signature, 163 input_example: schemas.Inputs, 164 ) -> Info: 165 with tempfile.TemporaryDirectory() as directory: 166 path = Path(directory) / "model.skops" 167 model.save_internal_model(path=str(path)) 168 return mlflow.pyfunc.log_model( 169 name=self.path, 170 python_model=str(self.CODE), 171 artifacts={"model": str(path)}, 172 model_config=model.model_dump(), 173 signature=signature, 174 input_example=input_example, 175 )
Saver for project models using the Mlflow PyFunc module.
Nothing is pickled: the adapter is logged as code (MLflow "models from code"), the
model params as its model_config, and the fitted internal model as a skops file.
158 @T.override 159 def save( 160 self, 161 model: models.Model, 162 signature: signers.Signature, 163 input_example: schemas.Inputs, 164 ) -> Info: 165 with tempfile.TemporaryDirectory() as directory: 166 path = Path(directory) / "model.skops" 167 model.save_internal_model(path=str(path)) 168 return mlflow.pyfunc.log_model( 169 name=self.path, 170 python_model=str(self.CODE), 171 artifacts={"model": str(path)}, 172 model_config=model.model_dump(), 173 signature=signature, 174 input_example=input_example, 175 )
Save a model in the model registry.
Arguments:
- model (models.Model): project model to save.
- signature (signers.Signature): model signature.
- input_example (schemas.Inputs): sample of inputs.
Returns:
Info: model saving information.
120 class Adapter(PythonModel): # type: ignore[misc] 121 """Adapt a custom model to the Mlflow PyFunc flavor. 122 123 https://mlflow.org/docs/latest/python_api/mlflow.pyfunc.html?#mlflow.pyfunc.PythonModel 124 """ 125 126 model: models.Model 127 128 def load_context(self, context: PythonModelContext) -> None: 129 """Rebuild the project model from its params and its internal model file. 130 131 Args: 132 context (mlflow.PythonModelContext): mlflow context with config and artifacts. 133 """ 134 model = pdt.TypeAdapter(models.ModelKind).validate_python(context.model_config) 135 self.model = model.load_internal_model(path=context.artifacts["model"]) 136 137 def predict( 138 self, 139 context: PythonModelContext, # noqa: ARG002 # required by mlflow PythonModel.predict 140 model_input: pd.DataFrame, 141 params: dict[str, T.Any] | None = None, # noqa: ARG002 # required by mlflow PythonModel.predict 142 ) -> schemas.Outputs: 143 """Generate predictions with a custom model for the given inputs. 144 145 Args: 146 context (mlflow.PythonModelContext): mlflow context. 147 model_input (pd.DataFrame): inputs to validate for the mlflow model. 148 params (dict[str, T.Any] | None): additional parameters. 149 150 Returns: 151 schemas.Outputs: validated outputs of the project model. 152 """ 153 # MLflow accepts pandas here and validates the logged signature; 154 # Pandera enforces the project's constraints before the typed model call. 155 inputs = schemas.InputsSchema.check(data=model_input) 156 return self.model.predict(inputs=inputs)
Adapt a custom model to the Mlflow PyFunc flavor.
https://mlflow.org/docs/latest/python_api/mlflow.pyfunc.html?#mlflow.pyfunc.PythonModel
128 def load_context(self, context: PythonModelContext) -> None: 129 """Rebuild the project model from its params and its internal model file. 130 131 Args: 132 context (mlflow.PythonModelContext): mlflow context with config and artifacts. 133 """ 134 model = pdt.TypeAdapter(models.ModelKind).validate_python(context.model_config) 135 self.model = model.load_internal_model(path=context.artifacts["model"])
Rebuild the project model from its params and its internal model file.
Arguments:
- context (mlflow.PythonModelContext): mlflow context with config and artifacts.
137 def predict( 138 self, 139 context: PythonModelContext, # noqa: ARG002 # required by mlflow PythonModel.predict 140 model_input: pd.DataFrame, 141 params: dict[str, T.Any] | None = None, # noqa: ARG002 # required by mlflow PythonModel.predict 142 ) -> schemas.Outputs: 143 """Generate predictions with a custom model for the given inputs. 144 145 Args: 146 context (mlflow.PythonModelContext): mlflow context. 147 model_input (pd.DataFrame): inputs to validate for the mlflow model. 148 params (dict[str, T.Any] | None): additional parameters. 149 150 Returns: 151 schemas.Outputs: validated outputs of the project model. 152 """ 153 # MLflow accepts pandas here and validates the logged signature; 154 # Pandera enforces the project's constraints before the typed model call. 155 inputs = schemas.InputsSchema.check(data=model_input) 156 return self.model.predict(inputs=inputs)
Generate predictions with a custom model for the given inputs.
Arguments:
- context (mlflow.PythonModelContext): mlflow context.
- model_input (pd.DataFrame): inputs to validate for the mlflow model.
- params (dict[str, T.Any] | None): additional parameters.
Returns:
schemas.Outputs: validated outputs of the project model.
178class BuiltinSaver(Saver): 179 """Saver for built-in models using an Mlflow flavor module. 180 181 https://mlflow.org/docs/latest/models.html#built-in-model-flavors 182 183 Parameters: 184 flavor (str): Mlflow flavor module to use for the serialization. 185 kwargs (dict[str, T.Any]): flavor-specific options for `log_model`. 186 e.g., sklearn saves with skops, which refuses to reload tree models 187 unless their types are trusted: `{"skops_trusted_types": [...]}`. 188 """ 189 190 KIND: T.Literal["BuiltinSaver"] = "BuiltinSaver" 191 192 flavor: str 193 kwargs: dict[str, T.Any] = {} 194 195 @T.override 196 def save( 197 self, 198 model: models.Model, 199 signature: signers.Signature, 200 input_example: schemas.Inputs, 201 ) -> Info: 202 builtin_model = model.get_internal_model() 203 module = getattr(mlflow, self.flavor) 204 return module.log_model( 205 builtin_model, 206 name=self.path, 207 signature=signature, 208 input_example=input_example, 209 **self.kwargs, 210 )
Saver for built-in models using an Mlflow flavor module.
https://mlflow.org/docs/latest/models.html#built-in-model-flavors
Arguments:
- flavor (str): Mlflow flavor module to use for the serialization.
- kwargs (dict[str, T.Any]): flavor-specific options for
log_model. e.g., sklearn saves with skops, which refuses to reload tree models unless their types are trusted:{"skops_trusted_types": [...]}.
195 @T.override 196 def save( 197 self, 198 model: models.Model, 199 signature: signers.Signature, 200 input_example: schemas.Inputs, 201 ) -> Info: 202 builtin_model = model.get_internal_model() 203 module = getattr(mlflow, self.flavor) 204 return module.log_model( 205 builtin_model, 206 name=self.path, 207 signature=signature, 208 input_example=input_example, 209 **self.kwargs, 210 )
Save a model in the model registry.
Arguments:
- model (models.Model): project model to save.
- signature (signers.Signature): model signature.
- input_example (schemas.Inputs): sample of inputs.
Returns:
Info: model saving information.
218class Loader(abc.ABC, pdt.BaseModel, strict=True, frozen=True, extra="forbid"): 219 """Base class for loading models from registry. 220 221 Separate model definition from deserialization. 222 e.g., to switch between deserialization flavors. 223 """ 224 225 KIND: str 226 227 class Adapter(abc.ABC): 228 """Adapt any model for the project inference.""" 229 230 @abc.abstractmethod 231 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 232 """Generate predictions with the internal model for the given inputs. 233 234 Args: 235 inputs (schemas.Inputs): validated inputs for the project model. 236 237 Returns: 238 schemas.Outputs: validated outputs of the project model. 239 """ 240 241 @abc.abstractmethod 242 def load(self, uri: str) -> Loader.Adapter: 243 """Load a model from the model registry. 244 245 Args: 246 uri (str): URI of a model to load. 247 248 Returns: 249 Loader.Adapter: model loaded. 250 """
Base class for loading models from registry.
Separate model definition from deserialization. e.g., to switch between deserialization flavors.
241 @abc.abstractmethod 242 def load(self, uri: str) -> Loader.Adapter: 243 """Load a model from the model registry. 244 245 Args: 246 uri (str): URI of a model to load. 247 248 Returns: 249 Loader.Adapter: model loaded. 250 """
Load a model from the model registry.
Arguments:
- uri (str): URI of a model to load.
Returns:
Loader.Adapter: model loaded.
227 class Adapter(abc.ABC): 228 """Adapt any model for the project inference.""" 229 230 @abc.abstractmethod 231 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 232 """Generate predictions with the internal model for the given inputs. 233 234 Args: 235 inputs (schemas.Inputs): validated inputs for the project model. 236 237 Returns: 238 schemas.Outputs: validated outputs of the project model. 239 """
Adapt any model for the project inference.
230 @abc.abstractmethod 231 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 232 """Generate predictions with the internal model for the given inputs. 233 234 Args: 235 inputs (schemas.Inputs): validated inputs for the project model. 236 237 Returns: 238 schemas.Outputs: validated outputs of the project model. 239 """
Generate predictions with the internal model for the given inputs.
Arguments:
- inputs (schemas.Inputs): validated inputs for the project model.
Returns:
schemas.Outputs: validated outputs of the project model.
253class CustomLoader(Loader): 254 """Loader for custom models using the Mlflow PyFunc module. 255 256 https://mlflow.org/docs/latest/python_api/mlflow.pyfunc.html 257 """ 258 259 KIND: T.Literal["CustomLoader"] = "CustomLoader" 260 261 class Adapter(Loader.Adapter): 262 """Adapt a custom model for the project inference.""" 263 264 def __init__(self, model: PyFuncModel) -> None: 265 """Initialize the adapter from an mlflow pyfunc model. 266 267 Args: 268 model (PyFuncModel): mlflow pyfunc model. 269 """ 270 self.model = model 271 272 @T.override 273 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 274 # model validation is already done in predict 275 outputs = self.model.predict(data=inputs) 276 return T.cast(schemas.Outputs, outputs) 277 278 @T.override 279 def load(self, uri: str) -> CustomLoader.Adapter: 280 model = mlflow.pyfunc.load_model(model_uri=uri) 281 return CustomLoader.Adapter(model=model)
Loader for custom models using the Mlflow PyFunc module.
https://mlflow.org/docs/latest/python_api/mlflow.pyfunc.html
278 @T.override 279 def load(self, uri: str) -> CustomLoader.Adapter: 280 model = mlflow.pyfunc.load_model(model_uri=uri) 281 return CustomLoader.Adapter(model=model)
Load a model from the model registry.
Arguments:
- uri (str): URI of a model to load.
Returns:
Loader.Adapter: model loaded.
261 class Adapter(Loader.Adapter): 262 """Adapt a custom model for the project inference.""" 263 264 def __init__(self, model: PyFuncModel) -> None: 265 """Initialize the adapter from an mlflow pyfunc model. 266 267 Args: 268 model (PyFuncModel): mlflow pyfunc model. 269 """ 270 self.model = model 271 272 @T.override 273 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 274 # model validation is already done in predict 275 outputs = self.model.predict(data=inputs) 276 return T.cast(schemas.Outputs, outputs)
Adapt a custom model for the project inference.
264 def __init__(self, model: PyFuncModel) -> None: 265 """Initialize the adapter from an mlflow pyfunc model. 266 267 Args: 268 model (PyFuncModel): mlflow pyfunc model. 269 """ 270 self.model = model
Initialize the adapter from an mlflow pyfunc model.
Arguments:
- model (PyFuncModel): mlflow pyfunc model.
272 @T.override 273 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 274 # model validation is already done in predict 275 outputs = self.model.predict(data=inputs) 276 return T.cast(schemas.Outputs, outputs)
Generate predictions with the internal model for the given inputs.
Arguments:
- inputs (schemas.Inputs): validated inputs for the project model.
Returns:
schemas.Outputs: validated outputs of the project model.
284class BuiltinLoader(Loader): 285 """Loader for built-in models using the Mlflow PyFunc module. 286 287 Note: use Mlflow PyFunc instead of flavors to use standard API. 288 289 https://mlflow.org/docs/latest/models.html#built-in-model-flavors 290 """ 291 292 KIND: T.Literal["BuiltinLoader"] = "BuiltinLoader" 293 294 class Adapter(Loader.Adapter): 295 """Adapt a builtin model for the project inference.""" 296 297 def __init__(self, model: PyFuncModel) -> None: 298 """Initialize the adapter from an mlflow pyfunc model. 299 300 Args: 301 model (PyFuncModel): mlflow pyfunc model. 302 """ 303 self.model = model 304 305 @T.override 306 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 307 columns = list(schemas.OutputsSchema.to_schema().columns) 308 outputs = self.model.predict(data=inputs) # unchecked data! 309 return schemas.Outputs(outputs, columns=columns, index=inputs.index) 310 311 @T.override 312 def load(self, uri: str) -> BuiltinLoader.Adapter: 313 model = mlflow.pyfunc.load_model(model_uri=uri) 314 return BuiltinLoader.Adapter(model=model)
Loader for built-in models using the Mlflow PyFunc module.
Note: use Mlflow PyFunc instead of flavors to use standard API.
https://mlflow.org/docs/latest/models.html#built-in-model-flavors
311 @T.override 312 def load(self, uri: str) -> BuiltinLoader.Adapter: 313 model = mlflow.pyfunc.load_model(model_uri=uri) 314 return BuiltinLoader.Adapter(model=model)
Load a model from the model registry.
Arguments:
- uri (str): URI of a model to load.
Returns:
Loader.Adapter: model loaded.
294 class Adapter(Loader.Adapter): 295 """Adapt a builtin model for the project inference.""" 296 297 def __init__(self, model: PyFuncModel) -> None: 298 """Initialize the adapter from an mlflow pyfunc model. 299 300 Args: 301 model (PyFuncModel): mlflow pyfunc model. 302 """ 303 self.model = model 304 305 @T.override 306 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 307 columns = list(schemas.OutputsSchema.to_schema().columns) 308 outputs = self.model.predict(data=inputs) # unchecked data! 309 return schemas.Outputs(outputs, columns=columns, index=inputs.index)
Adapt a builtin model for the project inference.
297 def __init__(self, model: PyFuncModel) -> None: 298 """Initialize the adapter from an mlflow pyfunc model. 299 300 Args: 301 model (PyFuncModel): mlflow pyfunc model. 302 """ 303 self.model = model
Initialize the adapter from an mlflow pyfunc model.
Arguments:
- model (PyFuncModel): mlflow pyfunc model.
305 @T.override 306 def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: 307 columns = list(schemas.OutputsSchema.to_schema().columns) 308 outputs = self.model.predict(data=inputs) # unchecked data! 309 return schemas.Outputs(outputs, columns=columns, index=inputs.index)
Generate predictions with the internal model for the given inputs.
Arguments:
- inputs (schemas.Inputs): validated inputs for the project model.
Returns:
schemas.Outputs: validated outputs of the project model.
322class Register(abc.ABC, pdt.BaseModel, strict=True, frozen=True, extra="forbid"): 323 """Base class for registring models to a location. 324 325 Separate model definition from its registration. 326 e.g., to change the model registry backend. 327 328 Parameters: 329 tags (dict[str, T.Any]): tags for the model. 330 """ 331 332 KIND: str 333 334 tags: dict[str, T.Any] = {} 335 336 @abc.abstractmethod 337 def register(self, name: str, model_uri: str) -> Version: 338 """Register a model given its name and URI. 339 340 Args: 341 name (str): name of the model to register. 342 model_uri (str): URI of a model to register. 343 344 Returns: 345 Version: information about the registered model. 346 """
Base class for registring models to a location.
Separate model definition from its registration. e.g., to change the model registry backend.
Arguments:
- tags (dict[str, T.Any]): tags for the model.
336 @abc.abstractmethod 337 def register(self, name: str, model_uri: str) -> Version: 338 """Register a model given its name and URI. 339 340 Args: 341 name (str): name of the model to register. 342 model_uri (str): URI of a model to register. 343 344 Returns: 345 Version: information about the registered model. 346 """
Register a model given its name and URI.
Arguments:
- name (str): name of the model to register.
- model_uri (str): URI of a model to register.
Returns:
Version: information about the registered model.
349class MlflowRegister(Register): 350 """Register for models in the Mlflow Model Registry. 351 352 https://mlflow.org/docs/latest/model-registry.html 353 """ 354 355 KIND: T.Literal["MlflowRegister"] = "MlflowRegister" 356 357 @T.override 358 def register(self, name: str, model_uri: str) -> Version: 359 return mlflow.register_model(name=name, model_uri=model_uri, tags=self.tags)
Register for models in the Mlflow Model Registry.
357 @T.override 358 def register(self, name: str, model_uri: str) -> Version: 359 return mlflow.register_model(name=name, model_uri=model_uri, tags=self.tags)
Register a model given its name and URI.
Arguments:
- name (str): name of the model to register.
- model_uri (str): URI of a model to register.
Returns:
Version: information about the registered model.