def test_deploy_tags(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    sparkml_model = SparkMLModel(model_data=MODEL_DATA_2,
                                 role=ROLE,
                                 sagemaker_session=sagemaker_session)
    model = PipelineModel(models=[framework_model, sparkml_model],
                          role=ROLE,
                          sagemaker_session=sagemaker_session)
    tags = [{"ModelName": "TestModel"}]
    model.deploy(instance_type=INSTANCE_TYPE,
                 initial_instance_count=1,
                 tags=tags)
    sagemaker_session.endpoint_from_production_variants.assert_called_with(
        name="mi-1-2017-10-10-14-14-15",
        production_variants=[{
            "InitialVariantWeight": 1,
            "ModelName": "mi-1-2017-10-10-14-14-15",
            "InstanceType": INSTANCE_TYPE,
            "InitialInstanceCount": 1,
            "VariantName": "AllTraffic",
        }],
        tags=tags,
        wait=True,
        kms_key=None,
        data_capture_config_dict=None,
    )
Esempio n. 2
0
def test_inference_pipeline_batch_transform(sagemaker_session):
    sparkml_model_data = sagemaker_session.upload_data(
        path=os.path.join(SPARKML_DATA_PATH, 'mleap_model.tar.gz'),
        key_prefix='integ-test-data/sparkml/model')
    xgb_model_data = sagemaker_session.upload_data(
        path=os.path.join(XGBOOST_DATA_PATH, 'xgb_model.tar.gz'),
        key_prefix='integ-test-data/xgboost/model')
    batch_job_name = 'test-inference-pipeline-batch-{}'.format(
        sagemaker_timestamp())
    sparkml_model = SparkMLModel(model_data=sparkml_model_data,
                                 env={'SAGEMAKER_SPARKML_SCHEMA': SCHEMA},
                                 sagemaker_session=sagemaker_session)
    xgb_image = get_image_uri(sagemaker_session.boto_region_name, 'xgboost')
    xgb_model = Model(model_data=xgb_model_data,
                      image=xgb_image,
                      sagemaker_session=sagemaker_session)
    model = PipelineModel(models=[sparkml_model, xgb_model],
                          role='SageMakerRole',
                          sagemaker_session=sagemaker_session,
                          name=batch_job_name)
    transformer = model.transformer(1, 'ml.m4.xlarge')
    transform_input_key_prefix = 'integ-test-data/sparkml_xgboost/transform'
    transform_input = transformer.sagemaker_session.upload_data(
        path=VALID_DATA_PATH, key_prefix=transform_input_key_prefix)

    with timeout_and_delete_model_with_transformer(
            transformer,
            sagemaker_session,
            minutes=TRANSFORM_DEFAULT_TIMEOUT_MINUTES):
        transformer.transform(transform_input,
                              content_type=CONTENT_TYPE_CSV,
                              job_name=batch_job_name)
        transformer.wait()
Esempio n. 3
0
def test_prepare_container_def(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    sparkml_model = SparkMLModel(
        model_data=MODEL_DATA_2,
        role=ROLE,
        sagemaker_session=sagemaker_session,
        env={"SAGEMAKER_DEFAULT_INVOCATIONS_ACCEPT": "text/csv"},
    )
    model = PipelineModel(models=[framework_model, sparkml_model],
                          role=ROLE,
                          sagemaker_session=sagemaker_session)
    assert model.pipeline_container_def(INSTANCE_TYPE) == [
        {
            "Environment": {
                "SAGEMAKER_PROGRAM": "blah.py",
                "SAGEMAKER_SUBMIT_DIRECTORY":
                "s3://mybucket/mi-1-2017-10-10-14-14-15/sourcedir.tar.gz",
                "SAGEMAKER_CONTAINER_LOG_LEVEL": "20",
                "SAGEMAKER_REGION": "us-west-2",
                "SAGEMAKER_ENABLE_CLOUDWATCH_METRICS": "false",
            },
            "Image": "mi-1",
            "ModelDataUrl": "s3://bucket/model_1.tar.gz",
        },
        {
            "Environment": {
                "SAGEMAKER_DEFAULT_INVOCATIONS_ACCEPT": "text/csv"
            },
            "Image": "246618743249.dkr.ecr.us-west-2.amazonaws.com" +
            "/sagemaker-sparkml-serving:2.2",
            "ModelDataUrl": "s3://bucket/model_2.tar.gz",
        },
    ]
def lambda_handler(event, context):
    schema_json = get_schema_json()
    bucket = os.environ['bucket']
    # Get the execution ID
    sess = sagemaker.Session()
    obj = s3.Object(bucket, 'execution.txt')
    exec_id = obj.get()['Body'].read().decode("utf-8")
    role = os.environ['role']
    print(exec_id)
    # Build variables
    training_job = f'{exec_id}-job'
    mleap_model_prefix = f'sagemaker/spark-preprocess-demo/{exec_id}/mleap-model'
    # Create models for Pipeline
    xgb_model = sagemaker.estimator.Estimator.attach(
        training_job).create_model()
    sparkml_data = 's3://{}/{}/{}'.format(os.environ['bucket'],
                                          mleap_model_prefix, 'model.tar.gz')
    sparkml_model = SparkMLModel(model_data=sparkml_data,
                                 env={'SAGEMAKER_SPARKML_SCHEMA': schema_json})

    # Create Pipeline Model
    model_name = 'inference-pipeline-' + exec_id
    sm_model = PipelineModel(name=model_name,
                             role=role,
                             models=[sparkml_model, xgb_model])
    sm_model.transformer(1, 'ml.m4.xlarge')
    event['model_name'] = model_name
    event['timestamp_prefix'] = exec_id
    return event
Esempio n. 5
0
def test_deploy_update_endpoint(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    endpoint_name = "endpoint-name"
    sparkml_model = SparkMLModel(model_data=MODEL_DATA_2,
                                 role=ROLE,
                                 sagemaker_session=sagemaker_session)
    model = PipelineModel(models=[framework_model, sparkml_model],
                          role=ROLE,
                          sagemaker_session=sagemaker_session)
    model.deploy(
        instance_type=INSTANCE_TYPE,
        initial_instance_count=1,
        endpoint_name=endpoint_name,
        update_endpoint=True,
    )

    sagemaker_session.create_endpoint_config.assert_called_with(
        name=model.name,
        model_name=model.name,
        initial_instance_count=INSTANCE_COUNT,
        instance_type=INSTANCE_TYPE,
        tags=None,
    )
    config_name = sagemaker_session.create_endpoint_config(
        name=model.name,
        model_name=model.name,
        initial_instance_count=INSTANCE_COUNT,
        instance_type=INSTANCE_TYPE,
    )
    sagemaker_session.update_endpoint.assert_called_with(
        endpoint_name, config_name)
    sagemaker_session.create_endpoint.assert_not_called()
def test_prepare_container_def(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    sparkml_model = SparkMLModel(
        model_data=MODEL_DATA_2,
        role=ROLE,
        sagemaker_session=sagemaker_session,
        env={'SAGEMAKER_DEFAULT_INVOCATIONS_ACCEPT': 'text/csv'})
    model = PipelineModel(models=[framework_model, sparkml_model],
                          role=ROLE,
                          sagemaker_session=sagemaker_session)
    assert model.pipeline_container_def(INSTANCE_TYPE) == [{
        'Environment': {
            'SAGEMAKER_PROGRAM': 'blah.py',
            'SAGEMAKER_SUBMIT_DIRECTORY':
            's3://mybucket/mi-1-2017-10-10-14-14-15/sourcedir.tar.gz',
            'SAGEMAKER_CONTAINER_LOG_LEVEL': '20',
            'SAGEMAKER_REGION': 'us-west-2',
            'SAGEMAKER_ENABLE_CLOUDWATCH_METRICS': 'false'
        },
        'Image':
        'mi-1',
        'ModelDataUrl':
        's3://bucket/model_1.tar.gz'
    }, {
        'Environment': {
            'SAGEMAKER_DEFAULT_INVOCATIONS_ACCEPT': 'text/csv'
        },
        'Image':
        '246618743249.dkr.ecr.us-west-2.amazonaws.com' +
        '/sagemaker-sparkml-serving:2.2',
        'ModelDataUrl':
        's3://bucket/model_2.tar.gz'
    }]
def test_inference_pipeline_model_deploy_and_update_endpoint(
        sagemaker_session, cpu_instance_type, alternative_cpu_instance_type):
    sparkml_data_path = os.path.join(DATA_DIR, "sparkml_model")
    xgboost_data_path = os.path.join(DATA_DIR, "xgboost_model")
    endpoint_name = "test-inference-pipeline-deploy-{}".format(
        sagemaker_timestamp())
    sparkml_model_data = sagemaker_session.upload_data(
        path=os.path.join(sparkml_data_path, "mleap_model.tar.gz"),
        key_prefix="integ-test-data/sparkml/model",
    )
    xgb_model_data = sagemaker_session.upload_data(
        path=os.path.join(xgboost_data_path, "xgb_model.tar.gz"),
        key_prefix="integ-test-data/xgboost/model",
    )

    with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
        sparkml_model = SparkMLModel(
            model_data=sparkml_model_data,
            env={"SAGEMAKER_SPARKML_SCHEMA": SCHEMA},
            sagemaker_session=sagemaker_session,
        )
        xgb_image = image_uris.retrieve("xgboost",
                                        sagemaker_session.boto_region_name,
                                        version="1",
                                        image_scope="inference")
        xgb_model = Model(model_data=xgb_model_data,
                          image_uri=xgb_image,
                          sagemaker_session=sagemaker_session)
        model = PipelineModel(
            models=[sparkml_model, xgb_model],
            role="SageMakerRole",
            predictor_cls=Predictor,
            sagemaker_session=sagemaker_session,
        )
        predictor = model.deploy(1,
                                 alternative_cpu_instance_type,
                                 endpoint_name=endpoint_name)
        endpoint_desc = sagemaker_session.sagemaker_client.describe_endpoint(
            EndpointName=endpoint_name)
        old_config_name = endpoint_desc["EndpointConfigName"]

        predictor.update_endpoint(initial_instance_count=1,
                                  instance_type=cpu_instance_type)

        endpoint_desc = sagemaker_session.sagemaker_client.describe_endpoint(
            EndpointName=endpoint_name)
        new_config_name = endpoint_desc["EndpointConfigName"]
        new_config = sagemaker_session.sagemaker_client.describe_endpoint_config(
            EndpointConfigName=new_config_name)

        assert old_config_name != new_config_name
        assert new_config["ProductionVariants"][0][
            "InstanceType"] == cpu_instance_type
        assert new_config["ProductionVariants"][0]["InitialInstanceCount"] == 1

    model.delete_model()
    with pytest.raises(Exception) as exception:
        sagemaker_session.sagemaker_client.describe_model(ModelName=model.name)
        assert "Could not find model" in str(exception.value)
def test_delete_model_without_deploy(sagemaker_session):
    pipeline_model = PipelineModel([],
                                   role=ROLE,
                                   sagemaker_session=sagemaker_session)

    expected_error_message = 'The SageMaker model must be created before attempting to delete.'
    with pytest.raises(ValueError, match=expected_error_message):
        pipeline_model.delete_model()
Esempio n. 9
0
def test_transformer(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    sparkml_model = SparkMLModel(model_data=MODEL_DATA_2,
                                 role=ROLE,
                                 sagemaker_session=sagemaker_session)
    model_name = "ModelName"
    model = PipelineModel(
        models=[framework_model, sparkml_model],
        role=ROLE,
        sagemaker_session=sagemaker_session,
        name=model_name,
    )

    instance_count = 55
    strategy = "MultiRecord"
    assemble_with = "Line"
    output_path = "s3://output/path"
    output_kms_key = "output:kms:key"
    accept = "application/jsonlines"
    env = {"my_key": "my_value"}
    max_concurrent_transforms = 20
    max_payload = 5
    tags = [{"my_tag": "my_value"}]
    volume_kms_key = "volume:kms:key"
    transformer = model.transformer(
        instance_type=INSTANCE_TYPE,
        instance_count=instance_count,
        strategy=strategy,
        assemble_with=assemble_with,
        output_path=output_path,
        output_kms_key=output_kms_key,
        accept=accept,
        env=env,
        max_concurrent_transforms=max_concurrent_transforms,
        max_payload=max_payload,
        tags=tags,
        volume_kms_key=volume_kms_key,
    )
    assert transformer.instance_type == INSTANCE_TYPE
    assert transformer.instance_count == instance_count
    assert transformer.strategy == strategy
    assert transformer.assemble_with == assemble_with
    assert transformer.output_path == output_path
    assert transformer.output_kms_key == output_kms_key
    assert transformer.accept == accept
    assert transformer.env == env
    assert transformer.max_concurrent_transforms == max_concurrent_transforms
    assert transformer.max_payload == max_payload
    assert transformer.tags == tags
    assert transformer.volume_kms_key == volume_kms_key
    assert transformer.model_name == model_name
Esempio n. 10
0
def test_inference_pipeline_model_deploy_with_update_endpoint(
    sagemaker_session, cpu_instance_type, alternative_cpu_instance_type
):
    sparkml_data_path = os.path.join(DATA_DIR, "sparkml_model")
    xgboost_data_path = os.path.join(DATA_DIR, "xgboost_model")
    endpoint_name = "test-inference-pipeline-deploy-{}".format(sagemaker_timestamp())
    sparkml_model_data = sagemaker_session.upload_data(
        path=os.path.join(sparkml_data_path, "mleap_model.tar.gz"),
        key_prefix="integ-test-data/sparkml/model",
    )
    xgb_model_data = sagemaker_session.upload_data(
        path=os.path.join(xgboost_data_path, "xgb_model.tar.gz"),
        key_prefix="integ-test-data/xgboost/model",
    )

    with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
        sparkml_model = SparkMLModel(
            model_data=sparkml_model_data,
            env={"SAGEMAKER_SPARKML_SCHEMA": SCHEMA},
            sagemaker_session=sagemaker_session,
        )
        xgb_image = get_image_uri(sagemaker_session.boto_region_name, "xgboost")
        xgb_model = Model(
            model_data=xgb_model_data, image=xgb_image, sagemaker_session=sagemaker_session
        )
        model = PipelineModel(
            models=[sparkml_model, xgb_model],
            role="SageMakerRole",
            sagemaker_session=sagemaker_session,
        )
        model.deploy(1, alternative_cpu_instance_type, endpoint_name=endpoint_name)
        old_endpoint = sagemaker_session.sagemaker_client.describe_endpoint(
            EndpointName=endpoint_name
        )
        old_config_name = old_endpoint["EndpointConfigName"]

        model.deploy(1, cpu_instance_type, update_endpoint=True, endpoint_name=endpoint_name)

        # Wait for endpoint to finish updating
        # Endpoint update takes ~7min. 40 retries * 30s sleeps = 20min timeout
        for _ in retries(40, "Waiting for 'InService' endpoint status", seconds_to_sleep=30):
            new_endpoint = sagemaker_session.sagemaker_client.describe_endpoint(
                EndpointName=endpoint_name
            )
            if new_endpoint["EndpointStatus"] == "InService":
                break

        new_config_name = new_endpoint["EndpointConfigName"]
        new_config = sagemaker_session.sagemaker_client.describe_endpoint_config(
            EndpointConfigName=new_config_name
        )

        assert old_config_name != new_config_name
        assert new_config["ProductionVariants"][0]["InstanceType"] == cpu_instance_type
        assert new_config["ProductionVariants"][0]["InitialInstanceCount"] == 1

    model.delete_model()
    with pytest.raises(Exception) as exception:
        sagemaker_session.sagemaker_client.describe_model(ModelName=model.name)
        assert "Could not find model" in str(exception.value)
Esempio n. 11
0
def inference_pipeline_ep(role, sess, spark_model_uri, region, bucket,
                          pipeline_model_name, endpoint_name, **context):
    timestamp_prefix = Variable.get("timestamp")
    # sm = boto3.client('sagemaker', region_name=region)
    s3client = boto3.client('s3', region_name=region)

    s3_sparkml_data_uri = spark_model_uri

    # Using S3 calls for listing model artifcats
    s3_xgb_objects = s3client.list_objects_v2(
        Bucket=bucket, StartAfter='sagemaker/spark-preprocess/model/xgboost/')
    obj_list = s3_xgb_objects['Contents']
    obj_list.sort(key=lambda x: x['LastModified'], reverse=False)
    xgboost_model_latest = obj_list[-1]['Key']
    s3_xgboost_model_uri = 's3://' + bucket + '/' + xgboost_model_latest

    # AirFlow XCOM feature
    # s3_xgboost_model_uri = context['task_instance'].xcom_pull(
    #    task_ids='xgboost_model_training')['Training']['ModelArtifacts']['S3ModelArtifacts']

    xgb_container = get_image_uri(sess.region_name,
                                  'xgboost',
                                  repo_version='0.90-1')

    schema_json = schema_utils.abalone_schema()

    sparkml_model = SparkMLModel(
        model_data=s3_sparkml_data_uri,
        role=role,
        sagemaker_session=sagemaker.session.Session(sess),
        env={'SAGEMAKER_SPARKML_SCHEMA': schema_json})

    xgb_model = Model(model_data=s3_xgboost_model_uri,
                      role=role,
                      sagemaker_session=sagemaker.session.Session(sess),
                      image=xgb_container)

    pipeline_model_name = pipeline_model_name

    sm_model = PipelineModel(name=pipeline_model_name,
                             role=role,
                             sagemaker_session=sagemaker.session.Session(sess),
                             models=[sparkml_model, xgb_model])

    endpoint_name = endpoint_name

    sm_model.deploy(initial_instance_count=1,
                    instance_type='ml.c4.xlarge',
                    endpoint_name=endpoint_name)
Esempio n. 12
0
def test_create_model_step_with_model_pipeline(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    sparkml_model = SparkMLModel(
        model_data="s3://bucket/model_2.tar.gz",
        role=ROLE,
        sagemaker_session=sagemaker_session,
        env={"SAGEMAKER_DEFAULT_INVOCATIONS_ACCEPT": "text/csv"},
    )
    model = PipelineModel(models=[framework_model, sparkml_model],
                          role=ROLE,
                          sagemaker_session=sagemaker_session)
    inputs = CreateModelInput(
        instance_type="c4.4xlarge",
        accelerator_type="ml.eia1.medium",
    )
    step = CreateModelStep(
        name="MyCreateModelStep",
        depends_on=["TestStep"],
        display_name="MyCreateModelStep",
        description="TestDescription",
        model=model,
        inputs=inputs,
    )
    step.add_depends_on(["SecondTestStep"])

    assert step.to_request() == {
        "Name": "MyCreateModelStep",
        "Type": "Model",
        "Description": "TestDescription",
        "DisplayName": "MyCreateModelStep",
        "DependsOn": ["TestStep", "SecondTestStep"],
        "Arguments": {
            "Containers": [
                {
                    "Environment": {
                        "SAGEMAKER_PROGRAM": "dummy_script.py",
                        "SAGEMAKER_SUBMIT_DIRECTORY":
                        "s3://my-bucket/mi-1-2017-10-10-14-14-15/sourcedir.tar.gz",
                        "SAGEMAKER_CONTAINER_LOG_LEVEL": "20",
                        "SAGEMAKER_REGION": "us-west-2",
                    },
                    "Image": "mi-1",
                    "ModelDataUrl": "s3://bucket/model_1.tar.gz",
                },
                {
                    "Environment": {
                        "SAGEMAKER_DEFAULT_INVOCATIONS_ACCEPT": "text/csv"
                    },
                    "Image":
                    "246618743249.dkr.ecr.us-west-2.amazonaws.com/sagemaker-sparkml-serving:2.4",
                    "ModelDataUrl": "s3://bucket/model_2.tar.gz",
                },
            ],
            "ExecutionRoleArn":
            "DummyRole",
        },
    }
    assert step.properties.ModelName.expr == {
        "Get": "Steps.MyCreateModelStep.ModelName"
    }
def test_deploy(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    sparkml_model = SparkMLModel(model_data=MODEL_DATA_2,
                                 role=ROLE,
                                 sagemaker_session=sagemaker_session)
    model = PipelineModel(models=[framework_model, sparkml_model],
                          role=ROLE,
                          sagemaker_session=sagemaker_session)
    model.deploy(instance_type=INSTANCE_TYPE, initial_instance_count=1)
    sagemaker_session.endpoint_from_production_variants.assert_called_with(
        'mi-1-2017-10-10-14-14-15', [{
            'InitialVariantWeight': 1,
            'ModelName': 'mi-1-2017-10-10-14-14-15',
            'InstanceType': INSTANCE_TYPE,
            'InitialInstanceCount': 1,
            'VariantName': 'AllTraffic'
        }], None)
def test_inference_pipeline_batch_transform(sagemaker_session,
                                            cpu_instance_type):
    sparkml_model_data = sagemaker_session.upload_data(
        path=os.path.join(SPARKML_DATA_PATH, "mleap_model.tar.gz"),
        key_prefix="integ-test-data/sparkml/model",
    )
    xgb_model_data = sagemaker_session.upload_data(
        path=os.path.join(XGBOOST_DATA_PATH, "xgb_model.tar.gz"),
        key_prefix="integ-test-data/xgboost/model",
    )
    batch_job_name = "test-inference-pipeline-batch-{}".format(
        sagemaker_timestamp())
    sparkml_model = SparkMLModel(
        model_data=sparkml_model_data,
        env={"SAGEMAKER_SPARKML_SCHEMA": SCHEMA},
        sagemaker_session=sagemaker_session,
    )
    xgb_image = image_uris.retrieve("xgboost",
                                    sagemaker_session.boto_region_name,
                                    version="1",
                                    image_scope="inference")
    xgb_model = Model(model_data=xgb_model_data,
                      image_uri=xgb_image,
                      sagemaker_session=sagemaker_session)
    model = PipelineModel(
        models=[sparkml_model, xgb_model],
        role="SageMakerRole",
        sagemaker_session=sagemaker_session,
        name=batch_job_name,
    )
    transformer = model.transformer(1, cpu_instance_type)
    transform_input_key_prefix = "integ-test-data/sparkml_xgboost/transform"
    transform_input = transformer.sagemaker_session.upload_data(
        path=VALID_DATA_PATH, key_prefix=transform_input_key_prefix)

    with timeout_and_delete_model_with_transformer(
            transformer,
            sagemaker_session,
            minutes=TRANSFORM_DEFAULT_TIMEOUT_MINUTES):
        transformer.transform(transform_input,
                              content_type="text/csv",
                              job_name=batch_job_name)
        transformer.wait()
def test_network_isolation(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    sparkml_model = SparkMLModel(model_data=MODEL_DATA_2,
                                 role=ROLE,
                                 sagemaker_session=sagemaker_session)
    model = PipelineModel(
        models=[framework_model, sparkml_model],
        role=ROLE,
        sagemaker_session=sagemaker_session,
        enable_network_isolation=True,
    )
    model.deploy(instance_type=INSTANCE_TYPE, initial_instance_count=1)

    sagemaker_session.create_model.assert_called_with(
        model.name,
        ROLE,
        [
            {
                "Image": "mi-1",
                "Environment": {
                    "SAGEMAKER_PROGRAM": "blah.py",
                    "SAGEMAKER_SUBMIT_DIRECTORY":
                    "s3://mybucket/mi-1-2017-10-10-14-14-15/sourcedir.tar.gz",
                    "SAGEMAKER_CONTAINER_LOG_LEVEL": "20",
                    "SAGEMAKER_REGION": "us-west-2",
                },
                "ModelDataUrl": "s3://bucket/model_1.tar.gz",
            },
            {
                "Image":
                "246618743249.dkr.ecr.us-west-2.amazonaws.com/sagemaker-sparkml-serving:2.2",
                "Environment": {},
                "ModelDataUrl": "s3://bucket/model_2.tar.gz",
            },
        ],
        vpc_config=None,
        enable_network_isolation=True,
    )
def test_delete_model(tfo, time, sagemaker_session):
    framework_model = DummyFrameworkModel(sagemaker_session)
    pipeline_model = PipelineModel(
        [framework_model], role=ROLE, sagemaker_session=sagemaker_session
    )
    pipeline_model.deploy(instance_type=INSTANCE_TYPE, initial_instance_count=1)

    pipeline_model.delete_model()
    sagemaker_session.delete_model.assert_called_with(pipeline_model.name)
def test_inference_pipeline_model_deploy(sagemaker_session, cpu_instance_type):
    sparkml_data_path = os.path.join(DATA_DIR, "sparkml_model")
    xgboost_data_path = os.path.join(DATA_DIR, "xgboost_model")
    endpoint_name = "test-inference-pipeline-deploy-{}".format(
        sagemaker_timestamp())
    sparkml_model_data = sagemaker_session.upload_data(
        path=os.path.join(sparkml_data_path, "mleap_model.tar.gz"),
        key_prefix="integ-test-data/sparkml/model",
    )
    xgb_model_data = sagemaker_session.upload_data(
        path=os.path.join(xgboost_data_path, "xgb_model.tar.gz"),
        key_prefix="integ-test-data/xgboost/model",
    )

    with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
        sparkml_model = SparkMLModel(
            model_data=sparkml_model_data,
            env={"SAGEMAKER_SPARKML_SCHEMA": SCHEMA},
            sagemaker_session=sagemaker_session,
        )
        xgb_image = image_uris.retrieve("xgboost",
                                        sagemaker_session.boto_region_name,
                                        version="1",
                                        image_scope="inference")
        xgb_model = Model(model_data=xgb_model_data,
                          image_uri=xgb_image,
                          sagemaker_session=sagemaker_session)
        model = PipelineModel(
            models=[sparkml_model, xgb_model],
            role="SageMakerRole",
            sagemaker_session=sagemaker_session,
            name=endpoint_name,
        )
        model.deploy(1, cpu_instance_type, endpoint_name=endpoint_name)
        predictor = Predictor(
            endpoint_name=endpoint_name,
            sagemaker_session=sagemaker_session,
            serializer=JSONSerializer,
            content_type="text/csv",
            accept="text/csv",
        )

        with open(VALID_DATA_PATH, "r") as f:
            valid_data = f.read()
            assert predictor.predict(valid_data) == "0.714013934135"

        with open(INVALID_DATA_PATH, "r") as f:
            invalid_data = f.read()
            assert predictor.predict(invalid_data) is None

    model.delete_model()
    with pytest.raises(Exception) as exception:
        sagemaker_session.sagemaker_client.describe_model(ModelName=model.name)
        assert "Could not find model" in str(exception.value)
Esempio n. 18
0
def test_inference_pipeline_model_deploy(sagemaker_session):
    sparkml_data_path = os.path.join(DATA_DIR, 'sparkml_model')
    xgboost_data_path = os.path.join(DATA_DIR, 'xgboost_model')
    endpoint_name = 'test-inference-pipeline-deploy-{}'.format(
        sagemaker_timestamp())
    sparkml_model_data = sagemaker_session.upload_data(
        path=os.path.join(sparkml_data_path, 'mleap_model.tar.gz'),
        key_prefix='integ-test-data/sparkml/model')
    xgb_model_data = sagemaker_session.upload_data(
        path=os.path.join(xgboost_data_path, 'xgb_model.tar.gz'),
        key_prefix='integ-test-data/xgboost/model')

    with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
        sparkml_model = SparkMLModel(model_data=sparkml_model_data,
                                     env={'SAGEMAKER_SPARKML_SCHEMA': SCHEMA},
                                     sagemaker_session=sagemaker_session)
        xgb_image = get_image_uri(sagemaker_session.boto_region_name,
                                  'xgboost')
        xgb_model = Model(model_data=xgb_model_data,
                          image=xgb_image,
                          sagemaker_session=sagemaker_session)
        model = PipelineModel(models=[sparkml_model, xgb_model],
                              role='SageMakerRole',
                              sagemaker_session=sagemaker_session,
                              name=endpoint_name)
        model.deploy(1, 'ml.m4.xlarge', endpoint_name=endpoint_name)
        predictor = RealTimePredictor(endpoint=endpoint_name,
                                      sagemaker_session=sagemaker_session,
                                      serializer=json_serializer,
                                      content_type=CONTENT_TYPE_CSV,
                                      accept=CONTENT_TYPE_CSV)

        with open(VALID_DATA_PATH, 'r') as f:
            valid_data = f.read()
            assert predictor.predict(valid_data) == '0.714013934135'

        with open(INVALID_DATA_PATH, 'r') as f:
            invalid_data = f.read()
            assert (predictor.predict(invalid_data) is None)

    model.delete_model()
    with pytest.raises(Exception) as exception:
        sagemaker_session.sagemaker_client.describe_model(ModelName=model.name)
        assert 'Could not find model' in str(exception.value)
def test_inference_pipeline_model_deploy(sagemaker_session):
    sparkml_data_path = os.path.join(DATA_DIR, 'sparkml_model')
    xgboost_data_path = os.path.join(DATA_DIR, 'xgboost_model')
    endpoint_name = 'test-inference-pipeline-deploy-{}'.format(sagemaker_timestamp())
    sparkml_model_data = sagemaker_session.upload_data(
        path=os.path.join(sparkml_data_path, 'mleap_model.tar.gz'),
        key_prefix='integ-test-data/sparkml/model')
    xgb_model_data = sagemaker_session.upload_data(
        path=os.path.join(xgboost_data_path, 'xgb_model.tar.gz'),
        key_prefix='integ-test-data/xgboost/model')
    schema = json.dumps({
        "input": [
            {
                "name": "Pclass",
                "type": "float"
            },
            {
                "name": "Embarked",
                "type": "string"
            },
            {
                "name": "Age",
                "type": "float"
            },
            {
                "name": "Fare",
                "type": "float"
            },
            {
                "name": "SibSp",
                "type": "float"
            },
            {
                "name": "Sex",
                "type": "string"
            }
        ],
        "output": {
            "name": "features",
            "struct": "vector",
            "type": "double"
        }
    })
    with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
        sparkml_model = SparkMLModel(model_data=sparkml_model_data,
                                     env={'SAGEMAKER_SPARKML_SCHEMA': schema},
                                     sagemaker_session=sagemaker_session)
        xgb_image = get_image_uri(sagemaker_session.boto_region_name, 'xgboost')
        xgb_model = Model(model_data=xgb_model_data, image=xgb_image,
                          sagemaker_session=sagemaker_session)
        model = PipelineModel(models=[sparkml_model, xgb_model], role='SageMakerRole',
                              sagemaker_session=sagemaker_session, name=endpoint_name)
        model.deploy(1, 'ml.m4.xlarge', endpoint_name=endpoint_name)
        predictor = RealTimePredictor(endpoint=endpoint_name, sagemaker_session=sagemaker_session,
                                      serializer=json_serializer, content_type=CONTENT_TYPE_CSV,
                                      accept=CONTENT_TYPE_CSV)

        valid_data = '1.0,C,38.0,71.5,1.0,female'
        assert predictor.predict(valid_data) == "0.714013934135"

        invalid_data = "1.0,28.0,C,38.0,71.5,1.0"
        assert (predictor.predict(invalid_data) is None)

    model.delete_model()
    with pytest.raises(Exception) as exception:
        sagemaker_session.sagemaker_client.describe_model(ModelName=model.name)
        assert 'Could not find model' in str(exception.value)
Esempio n. 20
0
def get_pipeline(
        region,
        sagemaker_project_arn=None,
        role=None,
        default_bucket='',
        pipeline_name='end-to-end-ml-sagemaker-pipeline',
        model_package_group_name='end-to-end-ml-sm-model-package-group',
        base_job_prefix='endtoendmlsm') -> Pipeline:
    """
    Gets the SM Pipeline.

    :param role: The execution role.
    :param bucket_name: The bucket where pipeline artifacts are stored.
    :param prefix: The prefix where pipeline artifacts are stored.
    :return: A Pipeline instance.
    """

    bucket_name = default_bucket
    prefix = 'endtoendmlsm'
    sagemaker_session = get_session(region, bucket_name)

    # ---------------------
    # Processing parameters
    # ---------------------
    # The path to the raw data.
    raw_data_path = 's3://gianpo-public/endtoendml/data/raw/predmain_raw_data_header.csv'.format(
        bucket_name, prefix)
    raw_data_path_param = ParameterString(name="raw_data_path",
                                          default_value=raw_data_path)
    # The output path to the training data.
    train_data_path = 's3://{0}/{1}/data/preprocessed/train/'.format(
        bucket_name, prefix)
    train_data_path_param = ParameterString(name="train_data_path",
                                            default_value=train_data_path)
    # The output path to the validation data.
    val_data_path = 's3://{0}/{1}/data/preprocessed/val/'.format(
        bucket_name, prefix)
    val_data_path_param = ParameterString(name="val_data_path",
                                          default_value=val_data_path)
    # The output path to the featurizer model.
    model_path = 's3://{0}/{1}/output/sklearn/'.format(bucket_name, prefix)
    model_path_param = ParameterString(name="model_path",
                                       default_value=model_path)
    # The instance type for the processing job.
    processing_instance_type_param = ParameterString(
        name="processing_instance_type", default_value='ml.m5.large')
    # The instance count for the processing job.
    processing_instance_count_param = ParameterInteger(
        name="processing_instance_count", default_value=1)
    # The train/test split ration parameter.
    train_test_split_ratio_param = ParameterString(
        name="train_test_split_ratio", default_value='0.2')
    # -------------------
    # Training parameters
    # -------------------
    # XGB hyperparameters.
    max_depth_param = ParameterString(name="max_depth", default_value='3')
    eta_param = ParameterString(name="eta", default_value='0.1')
    gamma_param = ParameterString(name="gamma", default_value='0')
    min_child_weight_param = ParameterString(name="min_child_weight",
                                             default_value='1')
    objective_param = ParameterString(name="objective",
                                      default_value='binary:logistic')
    num_round_param = ParameterString(name="num_round", default_value='10')
    eval_metric_param = ParameterString(name="eval_metric",
                                        default_value='auc')
    # The instance type for the training job.
    training_instance_type_param = ParameterString(
        name="training_instance_type", default_value='ml.m5.xlarge')
    # The instance count for the training job.
    training_instance_count_param = ParameterInteger(
        name="training_instance_count", default_value=1)
    # The training output path for the model.
    output_path = 's3://{0}/{1}/output/'.format(bucket_name, prefix)
    output_path_param = ParameterString(name="output_path",
                                        default_value=output_path)
    # --------------------------
    # Register model parameters
    # --------------------------
    # The default instance type for deployment.
    deploy_instance_type_param = ParameterString(name="deploy_instance_type",
                                                 default_value='ml.m5.2xlarge')
    # The approval status for models added to the registry.
    model_approval_status_param = ParameterString(
        name="model_approval_status", default_value='PendingManualApproval')
    # --------------------------
    # Processing Step
    # --------------------------
    sklearn_processor = SKLearnProcessor(
        role=role,
        instance_type=processing_instance_type_param,
        instance_count=processing_instance_count_param,
        framework_version='0.20.0')
    inputs = [
        ProcessingInput(input_name='raw_data',
                        source=raw_data_path_param,
                        destination='/opt/ml/processing/input')
    ]
    outputs = [
        ProcessingOutput(output_name='train_data',
                         source='/opt/ml/processing/train',
                         destination=train_data_path_param),
        ProcessingOutput(output_name='val_data',
                         source='/opt/ml/processing/val',
                         destination=val_data_path_param),
        ProcessingOutput(output_name='model',
                         source='/opt/ml/processing/model',
                         destination=model_path_param)
    ]
    code_path = os.path.join(BASE_DIR, 'dataprep/preprocess.py')
    processing_step = ProcessingStep(name='Processing',
                                     code=code_path,
                                     processor=sklearn_processor,
                                     inputs=inputs,
                                     outputs=outputs,
                                     job_arguments=[
                                         '--train-test-split-ratio',
                                         train_test_split_ratio_param
                                     ])
    # --------------------------
    # Training Step
    # --------------------------
    hyperparameters = {
        "max_depth": max_depth_param,
        "eta": eta_param,
        "gamma": gamma_param,
        "min_child_weight": min_child_weight_param,
        "silent": 0,
        "objective": objective_param,
        "num_round": num_round_param,
        "eval_metric": eval_metric_param
    }
    entry_point = 'train.py'
    source_dir = os.path.join(BASE_DIR, 'train/')
    code_location = 's3://{0}/{1}/code'.format(bucket_name, prefix)
    estimator = XGBoost(entry_point=entry_point,
                        source_dir=source_dir,
                        output_path=output_path_param,
                        code_location=code_location,
                        hyperparameters=hyperparameters,
                        instance_type=training_instance_type_param,
                        instance_count=training_instance_count_param,
                        framework_version="0.90-2",
                        py_version="py3",
                        role=role)
    training_step = TrainingStep(
        name='Training',
        estimator=estimator,
        inputs={
            'train':
            TrainingInput(
                s3_data=processing_step.properties.ProcessingOutputConfig.
                Outputs['train_data'].S3Output.S3Uri,
                content_type='text/csv'),
            'validation':
            TrainingInput(
                s3_data=processing_step.properties.ProcessingOutputConfig.
                Outputs['val_data'].S3Output.S3Uri,
                content_type='text/csv')
        })
    # --------------------------
    # Register Model Step
    # --------------------------
    code_location = 's3://{0}/{1}/code'.format(bucket_name, prefix)
    sklearn_model = SKLearnModel(
        name='end-to-end-ml-sm-skl-model-{0}'.format(str(int(time.time()))),
        model_data=processing_step.properties.ProcessingOutputConfig.
        Outputs['model'].S3Output.S3Uri,
        entry_point='inference.py',
        source_dir=os.path.join(BASE_DIR, 'deploy/sklearn/'),
        code_location=code_location,
        role=role,
        sagemaker_session=sagemaker_session,
        framework_version='0.20.0',
        py_version='py3')
    code_location = 's3://{0}/{1}/code'.format(bucket_name, prefix)
    xgboost_model = XGBoostModel(
        name='end-to-end-ml-sm-xgb-model-{0}'.format(str(int(time.time()))),
        model_data=training_step.properties.ModelArtifacts.S3ModelArtifacts,
        entry_point='inference.py',
        source_dir=os.path.join(BASE_DIR, 'deploy/xgboost/'),
        code_location=code_location,
        framework_version='0.90-2',
        py_version='py3',
        role=role,
        sagemaker_session=sagemaker_session)
    pipeline_model_name = 'end-to-end-ml-sm-xgb-skl-pipeline-{0}'.format(
        str(int(time.time())))
    pipeline_model = PipelineModel(name=pipeline_model_name,
                                   role=role,
                                   models=[sklearn_model, xgboost_model],
                                   sagemaker_session=sagemaker_session)

    register_model_step = RegisterModel(
        name='RegisterModel',
        content_types=['text/csv'],
        response_types=['application/json', 'text/csv'],
        inference_instances=[deploy_instance_type_param, 'ml.m5.large'],
        transform_instances=['ml.c5.4xlarge'],
        model_package_group_name=model_package_group_name,
        approval_status=model_approval_status_param,
        model=pipeline_model)
    # --------------------------
    # Pipeline
    # --------------------------

    pipeline = Pipeline(
        name=pipeline_name,
        parameters=[
            raw_data_path_param, train_data_path_param, val_data_path_param,
            model_path_param, processing_instance_type_param,
            processing_instance_count_param, train_test_split_ratio_param,
            max_depth_param, eta_param, gamma_param, min_child_weight_param,
            objective_param, num_round_param, eval_metric_param,
            training_instance_type_param, training_instance_count_param,
            output_path_param, deploy_instance_type_param,
            model_approval_status_param
        ],
        steps=[processing_step, training_step, register_model_step],
        sagemaker_session=sagemaker_session,
    )
    response = pipeline.upsert(role_arn=role)
    print(response["PipelineArn"])
    return pipeline
    def build_workflow_definition(self):
        """
        Build the workflow definition for the inference pipeline with all the states involved.

        Returns:
            :class:`~stepfunctions.steps.states.Chain`: Workflow definition as a chain of states involved in the the inference pipeline.
        """
        default_name = self.pipeline_name

        train_instance_type = self.preprocessor.train_instance_type
        train_instance_count = self.preprocessor.train_instance_count

        # Preprocessor for feature transformation
        preprocessor_train_step = TrainingStep(
            StepId.TrainPreprocessor.value,
            estimator=self.preprocessor,
            job_name=default_name + '/preprocessor-source',
            data=self.inputs,
        )
        preprocessor_model = self.preprocessor.create_model()
        preprocessor_model_step = ModelStep(
            StepId.CreatePreprocessorModel.value,
            instance_type=train_instance_type,
            model=preprocessor_model,
            model_name=default_name)
        preprocessor_transform_step = TransformStep(
            StepId.TransformInput.value,
            transformer=self.preprocessor.transformer(
                instance_count=train_instance_count,
                instance_type=train_instance_type,
                max_payload=20),
            job_name=default_name,
            model_name=default_name,
            data=self.inputs['train'],
            compression_type=self.compression_type,
            content_type=self.content_type)

        # Training
        train_instance_type = self.estimator.train_instance_type
        train_instance_count = self.estimator.train_instance_count

        training_step = TrainingStep(
            StepId.Train.value,
            estimator=self.estimator,
            job_name=default_name + '/estimator-source',
            data=self.inputs,
        )

        pipeline_model = PipelineModel(name='PipelineModel',
                                       role=self.estimator.role,
                                       models=[
                                           self.preprocessor.create_model(),
                                           self.estimator.create_model()
                                       ])
        pipeline_model_step = ModelStep(StepId.CreatePipelineModel.value,
                                        instance_type=train_instance_type,
                                        model=preprocessor_model,
                                        model_name=default_name)
        pipeline_model_step.parameters = self.pipeline_model_config(
            train_instance_type, pipeline_model)

        deployable_model = Model(model_data='', image='')

        # Deployment
        endpoint_config_step = EndpointConfigStep(
            StepId.ConfigureEndpoint.value,
            endpoint_config_name=default_name,
            model_name=default_name,
            initial_instance_count=train_instance_count,
            instance_type=train_instance_type)

        deploy_step = EndpointStep(
            StepId.Deploy.value,
            endpoint_name=default_name,
            endpoint_config_name=default_name,
        )

        return Chain([
            preprocessor_train_step, preprocessor_model_step,
            preprocessor_transform_step, training_step, pipeline_model_step,
            endpoint_config_step, deploy_step
        ])
Esempio n. 22
0
    preproc_model_url = args.preproc_model
    sm_role = get_sm_execution_role(False, region)

    preproc_model = SKLearnModel(model_data=preproc_model_url,
                                 source_dir=os.path.abspath(
                                     os.path.dirname(__file__)),
                                 role=sm_role,
                                 entry_point='infer_preproc.py',
                                 sagemaker_session=sess)

    ll_image = get_image_uri(region, 'linear-learner')

    ll_model = Model(model_data=model_url,
                     image=ll_image,
                     role=sm_role,
                     sagemaker_session=sess)

    timestamp_prefix = strftime("%Y-%m-%d-%H-%M-%S", gmtime())

    model_name = 'inference-pipeline-' + timestamp_prefix
    endpoint_name = 'inference-pipeline-ep-' + timestamp_prefix
    sm_model = PipelineModel(name=model_name,
                             role=sm_role,
                             models=[preproc_model, ll_model],
                             sagemaker_session=sess)
    print('Deploying SM EndPoint')
    sm_model.deploy(initial_instance_count=1,
                    instance_type='ml.c4.xlarge',
                    endpoint_name=endpoint_name)
    print(f'SageMaker deployed to endpoint - {endpoint_name}')