-
Notifications
You must be signed in to change notification settings - Fork 863
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
Add "RequestFormatter" config class to work with different inference platforms #436
Comments
Liked the idea of including formatter in mar. torch-model-archive util supports --extra-files flag, may be we can think of using same with some standard module/class naming convention. |
@htappen Instead of changing the base handler and adding new method i.e. getDefaultHandler that accepts Formatter, can we add new package named class BaseHandlerWithFormatter(**BaseHandler**)
def __init__(self):
self.request_formatter = None
def initialize(self, context):
**super(BaseHandlerWithFormatter, self).initialize(context)**
# Initialize formatter by using context
self.request_formatter = TFServingFormatter()
def handle(self, data, context):
if self.request_formatter:
data = self.request_formatter.parse_input(data)
**output = super(BaseHandlerWithFormatter, self).handle(data, context)**
if self.request_formatter:
output = self.request_formatter.format_output(data)
return output |
Thanks for taking a look! Implementing the request formatters in a replacement base class for BaseHandler won't work because then classes derived from BaseHandler (e.g. all the built-ins) won't get the behavior. However, another similar that could work would be to have the RequestFormatter wrap a handler object instead of the other way around: class RequestEnvelope(ABC):
def __init__(self, handler):
self._handler = handler
def initialize(self, context):
"""
For RequestEnvelope to be used like a Torch Handler, it needs to implement this method.
Simple calls the wrapped handler's initialize.
"""
self._handler.initialize(context)
def handle(self, data, context):
input_list = self.parse_input(data)
results = self._handler.handle(input_list, context)
output_list = self.format_output(results)
return output_list
@abstractmethod
def parse_input(self, data):
pass
@abstractmethod
def format_output(self, data):
pass To use this, someone would have to create a handler.py like MyHandler = TFRequestEnvelope(ImageClassifier()) Something about that feels a bit fragile, but let me think some more. |
#749 is now merged to master. Closing. |
Problem statement
Many model serving systems provide a signature for request bodies. Examples include:
Data scientists use these multi-framework systems to manage deployments of many different models, possibly written in different languages and frameworks. The platforms offer additional analytics on top of model serving, including skew detection, explanations and A/B testing. These platforms need a well-structured signature in order to both standardize calls across different frameworks and to understand the input data. To simplify support for many frameworks, though, these platforms will simply pass the request body along to the underlying model server.
Torchserve currently has no fixed request body signature. Data scientists are expected to define the MIME type they support and the structure of the request body. As a result, data scientists must manually write the code in their handler functions to accept inputs from one of the above model servers. This makes it challenging for an individual data scientist to integrate PyTorch serving into them. Worse yet, none of the Torchserve examples or built-in handlers are able to accept requests from these platforms.
Proposal
In order to (a) enable Torchserve to function with multi-framework model platforms while (b) maintaining compatibility with the existing, flexible data plane, we should introduce a property to BaseHandler that controls the input and output format.
It's expected that end users DO NOT implement these formatters themselves, nor do they have to consume the functionality manually. Instead, they either pass the formatter object into get_default_handler:
...or request it in torch-model-archiver:
We need to define an interface for these formatters. Their role is to strictly convert from an arbitrary format (e.g. JSON) to the format required by preprocess (a list of binary strings, dict, or vectors)
Of course, we'll need an implementation for compatibility with Seldon, KFServing and Cloud AI Platform:
Dependencies
The refactors outlined here make this a lot easier: #434
Implementation
Here's an example of the TFServingFormatter object. I will follow up with a complete file.
The text was updated successfully, but these errors were encountered: