This message was deleted.
# announcements
s
This message was deleted.
c
Great, love to hear how your adoption goes and if you have any feedback on the batching algorithm
j
Our models are built with Keras Functional API and logged in MLFlow, so i stumbled across all the errors mentioned in this ticket. https://github.com/bentoml/BentoML/issues/1188
however these are resolved with the workaround as per the issue
when micro batching is enable, i get such error.
Copy code
[2020-11-13 17:10:08,117] ERROR - Traceback (most recent call last):
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/bentoml/marshal/marshal.py", line 210, in request_dispatcher
    resp = await self.batch_handlers[api_name](req)
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/bentoml/marshal/dispatcher.py", line 141, in _func
    raise r
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/bentoml/marshal/dispatcher.py", line 201, in outbound_call
    outputs = await self.callback(tuple(d for _, d, _ in inputs_info))
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/bentoml/marshal/marshal.py", line 109, in _batch_handler_template
    return await func(requests, api_name)
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/bentoml/marshal/marshal.py", line 286, in _batch_handler_template
    return tuple(
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/bentoml/marshal/marshal.py", line 287, in <genexpr>
    aiohttp.web.Response(body=i.body, headers=i.headers, status=i.status)
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/aiohttp/web_response.py", line 540, in __init__
    super().__init__(status=status, reason=reason, headers=real_headers)
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/aiohttp/web_response.py", line 86, in __init__
    self.set_status(status, reason)
  File "/Users/jianshen/Desktop/Projects/reco-engine-v2/venv/lib/python3.8/site-packages/aiohttp/web_response.py", line 119, in set_status
    self._status = int(status)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
i printed out
i.status
-> it is
None
. For testing purposes I modify is so that it will return 200 when
i.status
is None , and it successfully ran with the right prediction
What would be the possible cause for the api server to return status code of None when using microbatching?
c
cc @Jiang
j
Hi @Jian Shen Yap. I haven't seen a similar problem before. May I take a look at your python script that defines the bento service?
j
Hi @Jiang, thanks for replying.
Copy code
import bentoml
import tensorflow as tf
import numpy as np

from bentoml.frameworks.tensorflow import TensorflowSavedModelArtifact
from bentoml.frameworks.keras import KerasModelArtifact
from bentoml.adapters import TfTensorInput
from bentoml.adapters import DataframeInput

import pandas as pd

@bentoml.env(infer_pip_packages=True)
# @bentoml.env(pip_packages=['tensorflow', 'numpy', 'pandas','scikit-learn', 'keras'])
@bentoml.artifacts([TensorflowSavedModelArtifact('model')])
class KerasModelService(bentoml.BentoService):
    @bentoml.api(input=DataframeInput(), mb_max_latency=1000, batch=True)
    def predict(self, df: pd.DataFrame):
        int_oh = np.append(np.zeros((2048 - df.shape[0], df.shape[1])),df,axis=0)
        exp_int_oh = np.expand_dims(int_oh, axis=1)
        batch_preds = self.artifacts.model(exp_int_oh.astype('float32'))
        preds_idx = tf.argsort(batch_preds,axis=-1,direction='DESCENDING',stable=False,name=None)
        
        return tf.reverse(preds_idx,[0])
In normal mode without micro batched enable, when i passed a dataframe with two rows [ […] , […]], I would get a prediction with 2 rows as well.
For extra information of the model This is the model summary of our model. It is built using keras functional api. We had to specify a batch size because we are using stateful GRU. When loaded as TensorflowSavedModel, the batch size shape will be
None
.
Let me know if any extra information is needed!
j
@Jian Shen Yap Hi. It seems that you are padding the batch size to 2048. It’s okay. But the size of returned value is also 2048, which mismatch the input.
j
@Jiang In non batching mode, it will truncate the output according to the length of the input. Are you implying that to have microbatching to work, the output length have to match the input length?
j
Yeah! When micro-batching enabled, bentoml would pack multiple user requests into one input (the data frame here). Thus, the returned value should have the same batch size with input, makes it possible to split the output accordingly.
I believe bentoml should handle this exception and provide better feedback when user returned mismatched output. I’ll open an issue to track this.
j
Currently, i believe bentoml will automatically truncate the output according to input length. Anyway I have modify the script according to your suggestion,
Copy code
class KerasModelService(bentoml.BentoService):
    @bentoml.api(input=DataframeInput(), mb_max_latency=1000, batch=True)
    def predict(self, df: pd.DataFrame):
        int_oh = np.append(np.zeros((2048 - df.shape[0], df.shape[1])),df,axis=0)
        exp_int_oh = np.expand_dims(int_oh, axis=1)
        batch_preds = self.artifacts.model(exp_int_oh.astype('float32'))
        preds_idx = tf.argsort(batch_preds,axis=-1,direction='DESCENDING',stable=False,name=None)
        rev = tf.reverse(preds_idx,[0])
        return rev[:df.shape[0],:]
the same error still occurs.
Copy code
class KerasModelService(bentoml.BentoService):
    @bentoml.api(input=DataframeInput(), mb_max_latency=1000, batch=True)
    def predict(self, df: pd.DataFrame):
        int_oh = np.append(np.zeros((2048 - df.shape[0], df.shape[1])),df,axis=0)
        exp_int_oh = np.expand_dims(int_oh, axis=1)
        batch_preds = self.artifacts.model(exp_int_oh.astype('float32'))
        preds_idx = tf.argsort(batch_preds,axis=-1,direction='DESCENDING',stable=False,name=None)
        rev = tf.reverse(preds_idx,[0])
        return "testing"
When i tested with a dummy string above, it will automatically truncate the string “testing” according to the size of the batch input, and it doesn’t throw an error for
i.status
, which makes me think that it is not the output length mismatch that causes this error to occur
After more debugging, i found out that
rev
is type of
EagerTensor
. After converting it to a
ndarray
and return it, microbatching works!
j
Congratulations. But EagerTensor should work, too. How about explicitly specifying the output adapter
output=TfTensorOutput()
like this?
Copy code
class KerasModelService(bentoml.BentoService):
    @bentoml.api(input=DataframeInput(), output=TfTensorOutput(), mb_max_latency=1000, batch=True)
    def predict(self, df: pd.DataFrame):
        int_oh = np.append(np.zeros((2048 - df.shape[0], df.shape[1])),df,axis=0)
        exp_int_oh = np.expand_dims(int_oh, axis=1)
        batch_preds = self.artifacts.model(exp_int_oh.astype('float32'))
        preds_idx = tf.argsort(batch_preds,axis=-1,direction='DESCENDING',stable=False,name=None)
        rev = tf.reverse(preds_idx,[0])
        return rev[:df.shape[0],:]
j
Hi @Jiang, I have tested your suggestion and a few more scenario: 1. return Eager Tensor 2. return a Tensor by using
convert_to_tensor
3. explicit specify output adapter
TfTensorOutput()
4. creating a dummy tensor
tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
None of these work, all of it throws the same error as i shown above
I am testing with a single request with the bentoml server running at microbatching mode. Perhaps there might be some incompatibility with tensor outputs?
j
I guess so. Thank you. Then it is a bug of TfTensorOutput now.
j
Yeah i supposed! Do you want me to create an issue for this bug?
j
j
Thanks @Jiang. Do you guys recommend to pull the latest code directly or wait for an official release to have this bug fixed
c
We recommend to use the official release, a new release is around the corner and we will be back to more frequent release cycle soon.