Hey there, I see that picklable_model is going to ...
# ask-for-help
n
Hey there, I see that picklable_model is going to be deprecated from warning messages starting v1.4. What am I supposed to use instead to save a custom object in the model store?
🏁 1
j
https://docs.bentoml.com/en/latest/build-with-bentoml/model-loading-and-management.html#save-a-model you can use the
bentoml.models.create
to save any arbitrary object/files into a bentoml model
n
Thanks, storing seems to work, but the
path_of
method/property of BentoModel seems to not exist, should I use
model.stored.path
instead?
j
how are you calling the
BentoModel
?
n
Copy code
bentomodel = bentoml.models.BentoModel("model:local")
then
bentomodel.path_of
does not exist
j
https://docs.bentoml.com/en/latest/build-with-bentoml/model-loading-and-management.html#save-a-model you would need to put it under a bentoml.service like the example. internally it will call
.resolve()
to get the model. if you are just testing it in a python shell, you would need to do
Copy code
bentomodel = bentoml.models.BentoModel("model:local").resolve()
bentomodel.path_of ...
n
Ok it was the resolve call, thanks, now it seems resolve the path correctly
model.resolve().path_of("model.pickle")
j
keep in mind, when writing the code in a
bentoml.service
you dont want to call
.resolve()
manually as it will be done internally
n
I was doing it inside
___init__
of the service,_ so I think I need to right?
j
no you don't need to. can you share your full code?
n
Yeah if I make it a member of the service I no longer need to call resolve, seems ok now, thanks!
t
Could you share the code snippet of your saving? I'm in a similar position having a mlflow.pyfunc.PythonModel class wrapping multiple models in a pipeline (including both pyro and sklearn) that I need to store in bentoml
n
Sure. I have a script called
build_bento.py
that is responsible for building the Bento and packaging the model with it, it looks something like this:
Copy code
# Download model from S3 to BentoML Model Store
    with bentoml.models.create(name=model_store_tag) as model_ref:
        S3Utils.download(model_path, model_ref.path)
	# Build Bento
    bentoml.build(
        service=bento_service, # Name of Service
        include=build_settings.BENTOFILE_INCLUDE_FILES, # List of files to include
        models=[model_store_tag], # List of Models to Package
        python={"packages": build_settings.ADDITIONAL_PACKAGES},
        docker={"base_image": base_image},
        envs=envs,
        build_ctx=bento_build_ctx,
        version=bento_tag,
    )
❤️ 1
t
And is it a nn.Module, keras or a custom python model or something fourth?
n
It's a Lightgbm model we keep in a pkl
t
@Jian Shen Yap I've got this simple combined model I'm using picklable_model to save. How would I go about saving that now?
Copy code
class CombinedModel(mlflow.pyfunc.PythonModel):
    """
    Combined for both the scaler and the pyro VAE
    """

    def __init__(self, scaler_uri, vae_uri):
        self.scaler_uri = scaler_uri
        self.vae_uri = vae_uri
        self.scaler: RobustScaler = None
        self.anomaly_detection: AnomalyDetectionVAE = None

    def load_context(self, context):
        """
        Loads artifacts from the specified :class:`~PythonModelContext` that can be used by
        :func:`~PythonModel.predict` when evaluating inputs. When loading an MLflow model with
        :func:`~load_model`, this method is called as soon as the :class:`~PythonModel` is
        constructed.

        The same :class:`~PythonModelContext` will also be available during calls to
        :func:`~PythonModel.predict`, but it may be more efficient to override this method
        and load artifacts from the context at model load time.

        Args:
            context: A :class:`~PythonModelContext` instance containing artifacts that the model
                     can use to perform inference.
        """
        self.scaler = mlflow.sklearn.load_model(self.scaler_uri)
        self.anomaly_detection = mlflow.pytorch.load_model(self.vae_uri)

    def predict(self, context, model_input):
        scaled_data = self.scaler.transform(model_input)
        input_tensor = torch.tensor(scaled_data, dtype=torch.float32)
        output = self.anomaly_detection.predict(input_tensor)
        return output
j
Copy code
with bentoml.models.create(
   name='my-local-model', # Name of the model in the Model Store
) as model_ref:
    # 1st. pickle your object

    # 2nd save your object to model_ref.path
https://docs.bentoml.com/en/latest/build-with-bentoml/model-loading-and-management.html#save-a-model