def output_fn(prediction, accept): """Format prediction output The default accept/content-type between containers for serial inference is JSON. We also want to set the ContentType or mimetype as the same value as accept so the next container can read the response payload correctly. """ accept = 'text/csv' if type(prediction) is not np.ndarray: prediction = prediction.toarray() if accept == "application/json": instances = [] for row in prediction.tolist(): instances.append({"features": row}) json_output = {"instances": instances} return worker.Response(json.dumps(json_output), mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), mimetype=accept) else: raise RuntimeException( "{} accept type is not supported by this script.".format(accept))
def output_fn(inferences, accept): """Format inferences output The default accept/content-type between containers for serial inference is JSON. We also want to set the ContentType or mimetype as the same value as accept so the next container can read the response payload correctly. """ if accept == "application/json": instances = [] for inference in inferences.tolist(): try: target, decision_boundary, prediction = inference instances.append({ "decision boundary": decision_boundary, "prediction": prediction, "target": target }) except ValueError: decision_boundary, prediction = inference instances.append({ "decision boundary": decision_boundary, "prediction": prediction }) json_output = {"instances": instances} return worker.Response(json.dumps(json_output), mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), mimetype=accept) else: raise RuntimeError( "{} accept type is not supported by this script.".format(accept))
def output_fn(prediction, accept): """Format prediction output The default accept/content-type between containers for serial inference is JSON. We also want to set the ContentType or mimetype as the same value as accept so the next container can read the response payload correctly. """ print("output") print(prediction) if accept == "application/json": instances = [] for row in prediction.tolist(): instances.append({"features": row}) h = np.asarray(row) string_row = [",".join(h.astype(str))][0] string_row_encode = string_row.encode() return worker.Response(string_row_encode, 'text/csv', mimetype='text/csv') json_output = {"instances": instances} return worker.Response(json.dumps(json_output), accept, mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), accept, mimetype=accept) else: raise RuntimeException( "{} accept type is not supported by this script.".format(accept))
def output_fn(prediction, accept_type): """Encodes prediction to accept type. The SageMaker Scikit-learn model server invokes this method with the result of prediction and serializes this according to the response MIME type. It expects the input to be numpy array and encodes to requested response MIME type. Parameters ---------- prediction : array-like the object returned from predict_fn accept_type : str the expected MIME type of the response Returns ------- : Response obj serialized predictions in accept type """ if isinstance(prediction, worker.Response): return prediction if _is_inverse_label_transform(): if accept_type == 'text/csv': return worker.Response(response=encoders.encode( prediction, accept_type), status=http_client.OK, mimetype=accept_type) else: return worker.Response( response=f"Accept type '{accept_type}' is not supported " f"during inverse label transformation.", status=413) if isinstance(prediction, tuple): X, y = prediction else: X, y = _split_features_target(prediction) if accept_type == 'application/x-recordio-protobuf': return worker.Response(response=encoders.array_to_recordio_protobuf( _sparsify_if_needed(X).astype('float32'), y.astype('float32') if y is not None else y), status=http_client.OK, mimetype=accept_type) if accept_type == 'text/csv': if y is not None: X = np.column_stack( (np.ravel(y), X.todense() if sparse.issparse(X) else X)) return worker.Response(response=encoders.encode(X, accept_type), status=http_client.OK, mimetype=accept_type) return worker.Response( response=f"Accept type '{accept_type}' is not supported.", status=http_client.NOT_ACCEPTABLE)
def execution_parameters_fn(): if _is_feature_transform(): return worker.Response(response='{"MaxPayloadInMB":1}', status=http_client.OK, mimetype="application/json") return worker.Response(response='{"MaxPayloadInMB":6}', status=http_client.OK, mimetype="application/json")
def output_fn(prediction, accept): if accept == "application/json": instances = [] for row in prediction.tolist(): instances.append({"features": row}) json_output = {"instances": instances} return worker.Response(json.dumps(json_output), mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), mimetype=accept) else: raise RuntimeException("{} accept type is not supported.".format(accept))
def transformation(): print("data: ", request.data[:100]) print("cookies: ", request.cookies) print("headers: ", dict(request.headers)) print("args: ", request.args) load_model() # We want to get the 'text/csv' bit from something like 'text/csv; charset=utf-8' content_type = request.headers['Content-Type'].split(';', 1)[0] print("Content type", content_type) accept = request.headers['Accept'] print("Accept", accept) input_data = request.data.decode() features = [] if content_type == "application/json": decoded_payload = json.loads(input_data) entries = [ entry['predicted_label'] for entry in decoded_payload['predictions'] ] predictions = np.array(entries) features = le.inverse_transform(predictions) elif content_type == "text/csv": entries = [int(float(label)) for label in input_data.split(',')] predictions = np.array(entries) features = le.inverse_transform(predictions) else: raise RuntimeError( "{} content type is not supported by this script.".format( content_type)) if accept == "application/json": instances = [] for row in features.tolist(): category = prepare_category_prediction(row) print("Category is: ", category) agent = get_agent_by_category(category) instances.append({"category": category, "agent": agent}) json_output = {"response": instances} return worker.Response(json.dumps(json_output), mimetype=accept) # TODO: use custom flag to indicate that this is in a pipeline rather than relying on the '*/*' elif accept == 'text/csv' or accept == '*/*': # TODO: this is wrong. fix it return worker.Response(encoders.encode(features, accept), mimetype='text/csv') else: raise RuntimeError( "{} accept type is not supported by this script.".format(accept))
def output_fn(prediction, accept): if accept == 'application/json': instances = [] for row in prediction.tolist(): instances.append({'features': row}) json_output = {'instances': instances} return worker.Response(json.dumps(json_output), accept=accept, mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), accept=accept, mimetype=accept) else: raise RuntimeError(f'{accept} accept type is not supported by this script.')
def execution_parameters_fn(): """Return the response for execution-parameters request used by SageMaker Batch transform. The SageMaker Scikit-learn model server invokes when execution-parameters endpoint is called. For the models generated by AutoML Jobs, returns the MaxPayloadInMB to be 1MB for feature transform used during inference and defaults to 6MB otherwise. """ if _is_feature_transform(): return worker.Response(response='{"MaxPayloadInMB":1}', status=http_client.OK, mimetype="application/json") return worker.Response(response='{"MaxPayloadInMB":6}', status=http_client.OK, mimetype="application/json")
def output_fn(prediction, accept): if (accept == 'text/csv; charset=utf-8') | (accept == 'text/csv'): return worker.Response(encoders.encode(prediction, accept), mimetype=accept) else: raise RuntimeError( "{} accept type is not supported by json_parser.".format(accept))
def output_fn(prediction, accept): """Format prediction output """ if accept == "application/json": return worker.Response(json.dumps(prediction), mimetype=accept) else: raise RuntimeException("{} content_type is not supported by this script.".format(accept))
def output_fn(prediction, accept): """Format prediction output The default accept/content-type between containers for serial inference is JSON. We also want to set the ContentType or mimetype as the same value as accept so the next container can read the response payload correctly. """ if accept == "application/json": return worker.Response(json.dumps(prediction), accept, mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), accept, mimetype=accept) else: raise ValueError( "{} accept type is not supported by this script.".format(accept))
def input_fn(request_body, request_content_type): """Decodes request body to 2D numpy array. The SageMaker Scikit-learn model server invokes this method to deserialize the request data into an object for prediction. Parameters ---------- request_body : str the request body request_content_type : str the media type for the request body Returns ------- : array-like decoded data as 2D numpy array """ content_type = request_content_type.lower( ) if request_content_type else "text/csv" content_type = content_type.split(";")[0].strip() if content_type == 'text/csv': if isinstance(request_body, str): byte_buffer = request_body.encode() else: byte_buffer = request_body val = read_csv_data(source=byte_buffer) logging.info(f"Shape of the requested data: '{val.shape}'") return val return worker.Response( response=f"'{request_content_type}' is an unsupported content type.", status=http_client.UNSUPPORTED_MEDIA_TYPE)
def predict_fn(input_object, model): """Generates prediction for the input_object based on the model. The SageMaker Scikit-learn model server invokes this method with the return value of the input_fn. This method invokes the loaded model's transform method, if it's expected to transform the input data and invokes the loaded model's inverse_label_transform, if the task is to perform inverse label transformation. Parameters ---------- input_object : array-like the object returned from input_fn model : AutoMLTransformer the model returned from model_fn Returns ------- : ndarray transformed input data or inverse transformed label data """ if isinstance(input_object, worker.Response): return input_object if _is_inverse_label_transform(): return model.inverse_label_transform(input_object.ravel().astype( np.float).astype(np.int)) try: return model.transform(input_object) except ValueError as e: return worker.Response(response='{}'.format( str(e) or 'Unknown error.'), status=http_client.BAD_REQUEST)
def output_fn(prediction, accept): """Format prediction output The default accept/content-type between containers for serial inference is JSON. We also want to set the ContentType or mimetype as the same value as accept so the next container can read the response payload correctly. """ return worker.Response("Not yet supported by script")
def output_fn(prediction_output, accept): if accept == 'application/x-npy': print('output_fn input is', prediction_output, 'in format', accept) return _npy_dumps(prediction_output), 'application/x-npy' elif accept == 'application/json': print('output_fn input is', prediction_output, 'in format', accept) return worker.Response(encoders.encode(prediction_output, accept), accept, mimetype=accept) else: raise ValueError('Accept header must be application/x-npy or application/json, but it is {}'.format(accept))
def default_output_fn(prediction, accept): """Function responsible to serialize the prediction for the response. Args: prediction (obj): prediction returned by predict_fn . accept (str): accept content-type expected by the client. Returns: (worker.Response): a Flask response object with the following args: * Args: response: the serialized data to return accept: the content-type that the data was transformed to. """ return worker.Response(encoders.encode(prediction, accept), mimetype=accept)
def output_fn(prediction, accept): pred_array_value = np.array(prediction) score = pred_array_value[0] if accept == "application/json": predicted_label = 1 if score > 0.5 else 0 return_value = { 'predictions': [{ 'score': score.astype(float), 'predicted_label': predicted_label }] } return worker.Response(json.dumps(return_value), mimetype=accept) elif accept == 'text/csv': return_value = 'yes' if score > 0.5 else 'no' return worker.Response(encoders.encode(prediction, accept), mimetype=accept) else: raise RuntimeException( "{} accept type is not supported.".format(accept))
def output_fn(prediction, accept): """Format prediction output The default accept/content-type between containers for serial inference is JSON. We also want to set the ContentType or mimetype as the same value as accept so the next container can read the response payload correctly. """ print("[output_fn] Prediction: ", prediction) print("[output_fn] Accept: ", accept) return worker.Response(encoders.encode(prediction, accept), accept, mimetype=accept)
def output_fn(prediction, accept): pred_array_value = np.array(prediction) score = pred_array_value[0] if accept == "application/json": predicted_label = 1 if score > 0.5 else 0 return_value = { "predictions": [{ "score": score.astype(float), "predicted_label": predicted_label }] } return worker.Response(json.dumps(return_value), mimetype=accept) elif accept == "text/csv": return_value = "yes" if score > 0.5 else "no" return worker.Response(encoders.encode(prediction, accept), mimetype=accept) else: raise RuntimeException( "{} accept type is not supported.".format(accept))
def output_fn(prediction, accept): print("OUTPUT FUNCTION START") print(prediction[:10]) print(type(prediction)) nrow = len(prediction) print('Prediction list number of rows:') print(str(nrow)) if accept == "application/json": return worker.Response(json.dumps(prediction), accept, mimetype=accept) elif accept == 'text/csv': output = worker.Response(encoders.encode(prediction, accept), accept, mimetype=accept) print(type(output)) print(str(output)) return output else: raise ValueError( "{} accept type is not supported by this script.".format(accept))
def output_fn(prediction, accept_type): if isinstance(prediction, worker.Response): return prediction if _is_inverse_label_transform(): if accept_type == 'text/csv': return worker.Response(response=encoders.encode( prediction, accept_type), status=http_client.OK, mimetype=accept_type) else: return worker.Response( response=f"Accept type '{accept_type}' is not supported " f"during inverse label transformation.", status=413) if isinstance(prediction, tuple): X, y = prediction else: X, y = _split_features_target(prediction) if accept_type == 'application/x-recordio-protobuf': return worker.Response(response=encoders.array_to_recordio_protobuf( _sparsify_if_needed(X).astype('float32'), y.astype('float32') if y is not None else y), status=http_client.OK, mimetype=accept_type) if accept_type == 'text/csv': if y is not None: X = np.column_stack( (np.ravel(y), X.todense() if sparse.issparse(X) else X)) return worker.Response(response=encoders.encode(X, accept_type), status=http_client.OK, mimetype=accept_type) return worker.Response( response=f"Accept type '{accept_type}' is not supported.", status=http_client.NOT_ACCEPTABLE)
def output_fn(prediction_output, accept): print(prediction_output) print(type(prediction_output)) if accept == 'application/x-npy': print('output_fn input is', prediction_output, 'in format', accept) buffer = BytesIO() np.save(buffer, prediction_output) return buffer.getvalue(), 'application/x-npy' elif accept == 'application/json': print('output_fn input is', prediction_output, 'in format', accept) return worker.Response(encoders.encode(prediction_output, accept), accept, mimetype=accept) else: raise ValueError('Accept header must be application/x-npy or application/json, but it is {}'.format(accept))
def default_output_fn(prediction, accept): """A default output_fn for PyTorch. Serializes predictions from predict_fn to JSON, CSV or NPZ format. Args: prediction: a prediction result from predict_fn accept: type which the output data needs to be serialized Returns: output data serialized """ if type(prediction) == torch.Tensor: prediction = prediction.detach().cpu().numpy() return worker.Response(encoders.encode(prediction, accept), accept)
def predict_fn(input_object, model): if isinstance(input_object, worker.Response): return input_object if _is_inverse_label_transform(): return model.inverse_label_transform(input_object.ravel().astype( np.float).astype(np.int)) try: return model.transform(input_object) except ValueError as e: return worker.Response(response='{}'.format( str(e) or 'Unknown error.'), status=http_client.BAD_REQUEST)
def output_fn(prediction, accept): """ Required by sagemaker to write the output from predict_fn, two choices are supported for this script json and csv. """ if accept == "application/json": instances = [] for row in prediction.values.tolist(): instances.append({"features": row}) json_output = {"instances": instances} return worker.Response(json.dumps(json_output), accept, mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), accept, mimetype=accept) else: raise RuntimeError( "{} accept type is not supported by this script.".format(accept))
def output_fn(prediction, accept): """Formato do output da predição O formato de aceitação (accept) do tipo de conteudo (accept/content-type) entre os containers é JSON. Nos tambem queremos definir o ContentType ou o mimetype como o mesmo valor como o formato de aceitação então o próximo container pode ler a resposta do payload corretamente. """ if accept == "application/json": instances = [] for row in prediction.tolist(): instances.append({"features": row}) json_output = {"instances": instances} json_output = pd.Series(json_output).to_json(orient='values') return worker.Response(json.dumps(json_output), mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), mimetype=accept) else: return worker.Response(encoders.encode(prediction, accept), mimetype=accept)
def output_fn(inferences, accept): """Format inferences output The default accept/content-type b/w containers for inference is JSON. We also want the ContentType/mimetype the same value as accept so the next container can read the response payload correctly. """ if accept == "application/json": instances = [] for inference in inferences.tolist(): if len(inference) == 4: target, pred_prob, prediction, expl = inference instances.append({ "pred_prob": pred_prob, "prediction": prediction, "target": target, "expl": expl }) elif len(inference) == 3: pred_prob, prediction, expl = inference instances.append({ "pred_prob": pred_prob, "prediction": prediction, "expl": expl }) else: pred_prob, prediction = inference instances.append({ "pred_prob": pred_prob, "prediction": prediction }) json_output = {"instances": instances} return worker.Response(json.dumps(json_output), mimetype=accept) elif accept == 'text/csv': return worker.Response(encoders.encode(prediction, accept), mimetype=accept) else: raise RuntimeError(f"{accept} is not supported by this script.")
def default_output_fn(self, prediction, accept): """Serialize the prediction into a response. Args: prediction (mxnet.nd.array): an MXNet NDArray that is the result of a prediction accept (str): the accept content type expected by the client Returns: sagemaker_containers.beta.framework.worker.Response: a Flask response object Raises: sagemaker_containers.beta.framework.errors.UnsupportedFormatError: if an unsupported accept type is used. """ if accept in self.VALID_CONTENT_TYPES: return worker.Response(encoders.encode(prediction.asnumpy().tolist(), accept), accept) else: raise errors.UnsupportedFormatError(accept)
def input_fn(request_body, request_content_type): content_type = request_content_type.lower( ) if request_content_type else "text/csv" content_type = content_type.split(";")[0].strip() if content_type == 'text/csv': if isinstance(request_body, str): byte_buffer = request_body.encode() else: byte_buffer = request_body val = read_csv_data(source=byte_buffer) logging.info(f"Shape of the requested data: '{val.shape}'") return val return worker.Response( response=f"'{request_content_type}' is an unsupported content type.", status=http_client.UNSUPPORTED_MEDIA_TYPE)