Sagemaker : How do I set content_type in Predictor (Sagemake > 2.0)?

Viewed 4605

Requesting assistance with the following error.

An error occurred (ModelError) when calling the InvokeEndpoint operation: Received client error (415) from model with message "Content-type application/octet-stream not supported. Supported content-type is text/csv, text/libsvm"

Here is the relevant code -

from sagemaker import image_uris
from sagemaker.estimator import Estimator

xgboost_hyperparameters = {
        "max_depth":"5",
        "eta":"0.2",
        "gamma":"4",
        "min_child_weight":"6",
        "subsample":"0.7",
        "num_round":"50"
}

xgboost_image = image_uris.retrieve("xgboost", boto3.Session().region_name, version="1")



estimator = Estimator(image_uri = xgboost_image,
                     hyperparameters = xgboost_hyperparameters,
                     role = role,
                     instance_count=1, 
                     instance_type='ml.m5.2xlarge', 
                      output_path= output_loc,
                     volume_size=5 )

from sagemaker.serializers import CSVSerializer
from sagemaker.deserializers import CSVDeserializer

train_input = sagemaker.inputs.TrainingInput(s3_data = train_loc, content_type='text/csv',s3_data_type = 'S3Prefix')
valid_input = sagemaker.inputs.TrainingInput(s3_data = validation_loc, content_type='text/csv',s3_data_type = 'S3Prefix')

estimator.CONTENT_TYPE = 'text/csv'
estimator.serializer = CSVSerializer()
estimator.deserializer = None

estimator.fit({'train':train_input, 'validation': valid_input})

# deploy model with data config
from sagemaker.model_monitor import DataCaptureConfig
from time import gmtime, strftime
s3_capture_upload_path = 's3://{}/{}/monitoring/datacapture'.format(bucket, prefix)
model_name = 'project3--model-' + strftime("%Y-%m-%d-%H-%M-%S", gmtime())
endpoint_name = 'project3-endpoint'
data_capture_configuration = DataCaptureConfig(
                        enable_capture = True,
                        sampling_percentage=100,
                        destination_s3_uri=s3_capture_upload_path  )

deploy = estimator.deploy(initial_instance_count = 1,
                          instance_type = 'ml.m4.xlarge'    ,
                          data_capture_config=data_capture_configuration,
                          model_name=model_name,
                          endpoint_name = endpoint_name
                         )

Then I face the error in the Predictor

from sagemaker.predictor import Predictor

predictor = Predictor(endpoint_name=endpoint_name)
with open('test.csv', 'r') as f:
    for row in f:
        print(row)
        payload = row.rstrip('\n')
        response = predictor.predict(data=payload[2:])
        sleep(0.5)
print('done!')
 

I looked at these links but haven't found an answer

  1. https://github.com/aws-samples/reinvent2019-aim362-sagemaker-debugger-model-monitor/blob/master/02_deploy_and_monitor/deploy_and_monitor.ipynb
  2. How can I specify content_type in a training job of XGBoost from Sagemaker in Python?
  3. https://github.com/aws/amazon-sagemaker-examples/issues/729
3 Answers

First, please make sure which SDK version you are using. AWS made breaking changes between 1.x and 2.x. Even worse, the sagemaker SDK on notebook instance can be different from that in the sagemaker studio depending on the regions.

Please see How to use Serializer and Deserializer in Sagemaker 2 as well as AWS changed serialize/deserialize stuff.

Behavior for serialization of input data and deserialization of result data can be configured through initializer arguments.

Please try:

from sagemaker.serializers import CSVSerializer
predictor.serializer = CSVSerializer()

Or by setting None to the serializer, you can have full control over serialize/deserialize in your code.

predictor.serializer=None

As seen here, predict()'s initial_args is "Default arguments for boto3 invoke_endpoint call.

For me, this worked:

predictor.predict(review_input, initial_args={'ContentType': 'text/plain'})

Using the reference API for predictor here with initial_args

predictor.predict(review_input, initial_args={'ContentType': 'text/csv'})

Related