Exemple #1
0
def test_deploy_replace_in_asynchronous_mode_returns_before_endpoint_creation_completes(
        pretrained_model, sagemaker_client):
    endpoint_update_latency = 10
    get_sagemaker_backend(
        sagemaker_client.meta.region_name).set_endpoint_update_latency(
            endpoint_update_latency)

    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_uri=pretrained_model.model_uri,
               mode=mfs.DEPLOYMENT_MODE_CREATE,
               synchronous=True)

    update_start_time = time.time()
    mfs.deploy(app_name=app_name,
               model_uri=pretrained_model.model_uri,
               mode=mfs.DEPLOYMENT_MODE_REPLACE,
               synchronous=False,
               archive=True)
    update_end_time = time.time()

    assert (update_end_time - update_start_time) < endpoint_update_latency
    endpoint_description = sagemaker_client.describe_endpoint(
        EndpointName=app_name)
    assert endpoint_description["EndpointStatus"] == Endpoint.STATUS_UPDATING
Exemple #2
0
def test_deploy_creates_sagemaker_and_s3_resources_with_expected_names_from_local(
        pretrained_model, sagemaker_client):
    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_uri=pretrained_model.model_uri,
               mode=mfs.DEPLOYMENT_MODE_CREATE)

    region_name = sagemaker_client.meta.region_name
    s3_client = boto3.client("s3", region_name=region_name)
    default_bucket = mfs._get_default_s3_bucket(region_name)
    endpoint_description = sagemaker_client.describe_endpoint(
        EndpointName=app_name)
    endpoint_production_variants = endpoint_description["ProductionVariants"]
    assert len(endpoint_production_variants) == 1
    model_name = endpoint_production_variants[0]["VariantName"]
    assert model_name in [
        model["ModelName"]
        for model in sagemaker_client.list_models()["Models"]
    ]
    object_names = [
        entry["Key"]
        for entry in s3_client.list_objects(Bucket=default_bucket)["Contents"]
    ]
    assert any([model_name in object_name for object_name in object_names])
    assert any([
        app_name in config["EndpointConfigName"] for config in
        sagemaker_client.list_endpoint_configs()["EndpointConfigs"]
    ])
    assert app_name in [
        endpoint["EndpointName"]
        for endpoint in sagemaker_client.list_endpoints()["Endpoints"]
    ]
def test_deploy_creates_sagemaker_resources_with_expected_names(pretrained_model, sagemaker_client):
    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_path=pretrained_model.model_path,
               run_id=pretrained_model.run_id,
               mode=mfs.DEPLOYMENT_MODE_CREATE)

    models_response = sagemaker_client.list_models()
    found_matching_model = False
    for model in models_response["Models"]:
        if app_name in model["ModelName"]:
            found_matching_model = True
            break
    assert found_matching_model

    endpoint_configs_response = sagemaker_client.list_endpoint_configs()
    found_matching_config = False
    for config in endpoint_configs_response["EndpointConfigs"]:
        if app_name in config["EndpointConfigName"]:
            found_matching_config = True
            break
    assert found_matching_config

    endpoints_response = sagemaker_client.list_endpoints()
    assert app_name in [endpoint["EndpointName"] for endpoint in endpoints_response["Endpoints"]]
Exemple #4
0
def test_deploy_in_create_mode_throws_exception_after_endpoint_creation_fails(
        pretrained_model, sagemaker_client):
    endpoint_creation_latency = 10
    sagemaker_backend = get_sagemaker_backend(
        sagemaker_client.meta.region_name)
    sagemaker_backend.set_endpoint_update_latency(endpoint_creation_latency)

    boto_caller = botocore.client.BaseClient._make_api_call

    def fail_endpoint_creations(self, operation_name, operation_kwargs):
        """
        Processes all boto3 client operations according to the following rules:
        - If the operation is an endpoint creation, create the endpoint and set its status to
          ``Endpoint.STATUS_FAILED``.
        - Else, execute the client operation as normal
        """
        result = boto_caller(self, operation_name, operation_kwargs)
        if operation_name == "CreateEndpoint":
            endpoint_name = operation_kwargs["EndpointName"]
            sagemaker_backend.set_endpoint_latest_operation(
                endpoint_name=endpoint_name,
                operation=EndpointOperation.create_unsuccessful(
                    latency_seconds=endpoint_creation_latency))
        return result

    with mock.patch("botocore.client.BaseClient._make_api_call", new=fail_endpoint_creations),\
            pytest.raises(MlflowException) as exc:
        mfs.deploy(app_name="test-app",
                   model_uri=pretrained_model.model_uri,
                   mode=mfs.DEPLOYMENT_MODE_CREATE)

    assert "deployment operation failed" in exc.value.message
    assert exc.value.error_code == ErrorCode.Name(INTERNAL_ERROR)
Exemple #5
0
def deploy(config_path, job_id):
    with open(config_path, 'r') as f:
        config = json.load(f)

    app_name = config['deploy']['app_name']
    instance_type = config['deploy']['instance_type']
    instance_count = config['deploy']['instance_count']
    region = config['deploy']['region']
    role = config['role']
    model_name = config['model_name']
    model_bucket = re.sub('s3://', '', config['model_bucket'])
    model_artifact = config['model_artifact']
    model_path = '{}/output/{}'.format(job_id, model_artifact)

    logger.info(
        'Deploying model with parameters '
        '[app-name="{}", instance-type="{}", instance-count={}, region="{}", model-path="{}"]'
        .format(app_name, instance_type, instance_count, region, model_path))

    s3 = boto3.client('s3')
    s3.download_file(model_bucket, model_path, model_artifact)

    unpack(model_artifact)

    sagemaker.deploy(app_name=app_name,
                     model_uri=model_name,
                     execution_role_arn=role,
                     region_name=region,
                     mode='replace',
                     instance_type=instance_type,
                     instance_count=instance_count)
def test_deployment_with_unsupported_flavor_throws_value_error(pretrained_model):
    unsupported_flavor = "this is not a valid flavor"
    with pytest.raises(ValueError):
        mfs.deploy(app_name="bad_flavor",
                   model_path=pretrained_model.model_path,
                   run_id=pretrained_model.run_id,
                   flavor=unsupported_flavor)
def test_deployment_with_missing_flavor_throws_value_error(pretrained_model):
    missing_flavor = "mleap"
    with pytest.raises(ValueError):
        mfs.deploy(app_name="missing-flavor",
                   model_path=pretrained_model.model_path,
                   run_id=pretrained_model.run_id,
                   flavor=missing_flavor)
Exemple #8
0
def test_deploy_creates_sagemaker_and_s3_resources_with_expected_names(
        pretrained_model, sagemaker_client):
    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_path=pretrained_model.model_path,
               run_id=pretrained_model.run_id,
               mode=mfs.DEPLOYMENT_MODE_CREATE)

    region_name = sagemaker_client.meta.region_name
    s3_client = boto3.client("s3", region_name=region_name)
    default_bucket = mfs._get_default_s3_bucket(region_name)
    object_names = [
        entry["Key"]
        for entry in s3_client.list_objects(Bucket=default_bucket)["Contents"]
    ]
    assert any([
        pretrained_model.run_id in object_name for object_name in object_names
    ])
    assert any([
        app_name in model["ModelName"]
        for model in sagemaker_client.list_models()["Models"]
    ])
    assert any([
        app_name in config["EndpointConfigName"] for config in
        sagemaker_client.list_endpoint_configs()["EndpointConfigs"]
    ])
    assert app_name in [
        endpoint["EndpointName"]
        for endpoint in sagemaker_client.list_endpoints()["Endpoints"]
    ]
Exemple #9
0
def test_deployment_with_missing_flavor_raises_exception(pretrained_model):
    missing_flavor = "mleap"
    with pytest.raises(MlflowException) as exc:
        mfs.deploy(app_name="missing-flavor",
                   model_uri=pretrained_model.model_uri,
                   flavor=missing_flavor)

    assert exc.value.error_code == ErrorCode.Name(RESOURCE_DOES_NOT_EXIST)
Exemple #10
0
def test_deployment_with_unsupported_flavor_raises_exception(pretrained_model):
    unsupported_flavor = "this is not a valid flavor"
    with pytest.raises(MlflowException) as exc:
        mfs.deploy(app_name="bad_flavor",
                   model_uri=pretrained_model.model_uri,
                   flavor=unsupported_flavor)

    assert exc.value.error_code == ErrorCode.Name(INVALID_PARAMETER_VALUE)
Exemple #11
0
def test_deployment_with_assume_role_arn(pretrained_model, sagemaker_client):
    app_name = "deploy_with_assume_role_arn"
    mfs.deploy(app_name=app_name,
               model_uri=pretrained_model.model_uri,
               assume_role_arn="arn:aws:iam::123456789012:role/assumed_role")
    assert app_name in [
        endpoint["EndpointName"]
        for endpoint in sagemaker_client.list_endpoints()["Endpoints"]
    ]
Exemple #12
0
def test_deployment_with_missing_flavor_raises_exception(pretrained_model):
    missing_flavor = "mleap"
    match = "The specified model does not contain the specified deployment flavor"
    with pytest.raises(MlflowException, match=match) as exc:
        mfs.deploy(app_name="missing-flavor",
                   model_uri=pretrained_model.model_uri,
                   flavor=missing_flavor)

    assert exc.value.error_code == ErrorCode.Name(RESOURCE_DOES_NOT_EXIST)
Exemple #13
0
def deploy(run_id, region, execution_role_arn, instance_type, app_name):
    assert "MLFLOW_SAGEMAKER_DEPLOY_IMG_URL" in os.environ

    model_uri = "runs:/" + run_id + "/model"
    mfs.deploy(app_name=app_name,
               model_uri=model_uri,
               region_name=region,
               mode="replace",
               execution_role_arn=execution_role_arn,
               instance_type=instance_type)
def test_deployment_of_model_with_no_supported_flavors_throws_value_error(pretrained_model):
    logged_model_path = _get_model_log_dir(pretrained_model.model_path, pretrained_model.run_id)
    model_config_path = os.path.join(logged_model_path, "MLmodel")
    model_config = Model.load(model_config_path)
    del model_config.flavors[mlflow.pyfunc.FLAVOR_NAME]
    model_config.save(path=model_config_path)

    with pytest.raises(ValueError):
        mfs.deploy(app_name="missing-flavor",
                   model_path=logged_model_path,
                   flavor=None)
Exemple #15
0
def test_attempting_to_deploy_in_asynchronous_mode_without_archiving_throws_exception(
        pretrained_model):
    with pytest.raises(MlflowException) as exc:
        mfs.deploy(app_name="test-app",
                   model_uri=pretrained_model.model_uri,
                   mode=mfs.DEPLOYMENT_MODE_CREATE,
                   archive=False,
                   synchronous=False)

    assert "Resources must be archived" in exc.value.message
    assert exc.value.error_code == ErrorCode.Name(INVALID_PARAMETER_VALUE)
Exemple #16
0
def test_deployment_with_non_existent_assume_role_arn_raises_exception(
        pretrained_model):

    with pytest.raises(botocore.exceptions.ClientError) as exc:
        mfs.deploy(app_name="bad_assume_role_arn",
                   model_uri=pretrained_model.model_uri,
                   assume_role_arn=
                   "arn:aws:iam::123456789012:role/non-existent-role-arn")

    assert str(
        exc.value
    ) == "An error occurred (NoSuchEntity) when calling the GetRole operation: Role non-existent-role-arn not found"
Exemple #17
0
def test_deployment_of_model_with_no_supported_flavors_raises_exception(pretrained_model):
    logged_model_path = _download_artifact_from_uri(pretrained_model.model_uri)
    model_config_path = os.path.join(logged_model_path, "MLmodel")
    model_config = Model.load(model_config_path)
    del model_config.flavors[mlflow.pyfunc.FLAVOR_NAME]
    model_config.save(path=model_config_path)

    match = "The specified model does not contain any of the supported flavors for deployment"
    with pytest.raises(MlflowException, match=match) as exc:
        mfs.deploy(app_name="missing-flavor", model_uri=logged_model_path, flavor=None)

    assert exc.value.error_code == ErrorCode.Name(RESOURCE_DOES_NOT_EXIST)
Exemple #18
0
def test_deployment_with_non_existent_assume_role_arn_raises_exception(
        pretrained_model):

    match = (r"An error occurred \(NoSuchEntity\) when calling the GetRole "
             r"operation: Role non-existent-role-arn not found")
    with pytest.raises(botocore.exceptions.ClientError, match=match):
        mfs.deploy(
            app_name="bad_assume_role_arn",
            model_uri=pretrained_model.model_uri,
            assume_role_arn=
            "arn:aws:iam::123456789012:role/non-existent-role-arn",
        )
Exemple #19
0
def test_deployment_of_model_with_no_supported_flavors_raises_exception(pretrained_model):
    logged_model_path = _get_model_log_dir(pretrained_model.model_path, pretrained_model.run_id)
    model_config_path = os.path.join(logged_model_path, "MLmodel")
    model_config = Model.load(model_config_path)
    del model_config.flavors[mlflow.pyfunc.FLAVOR_NAME]
    model_config.save(path=model_config_path)

    with pytest.raises(MlflowException) as exc:
        mfs.deploy(app_name="missing-flavor",
                   model_path=logged_model_path,
                   flavor=None)

    assert exc.value.error_code == ErrorCode.Name(RESOURCE_DOES_NOT_EXIST)
Exemple #20
0
def test_deploying_application_with_preexisting_name_in_create_mode_throws_exception(
        pretrained_model):
    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_uri=pretrained_model.model_uri,
               mode=mfs.DEPLOYMENT_MODE_CREATE)

    with pytest.raises(MlflowException) as exc:
        mfs.deploy(app_name=app_name,
                   model_uri=pretrained_model.model_uri,
                   mode=mfs.DEPLOYMENT_MODE_CREATE)

    assert "an application with the same name already exists" in exc.value.message
    assert exc.value.error_code == ErrorCode.Name(INVALID_PARAMETER_VALUE)
Exemple #21
0
def test_deploy_in_replace_mode_with_archiving_does_not_delete_resources(
        pretrained_model, sagemaker_client):
    region_name = sagemaker_client.meta.region_name
    sagemaker_backend = get_sagemaker_backend(region_name)
    sagemaker_backend.set_endpoint_update_latency(5)

    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_path=pretrained_model.model_path,
               run_id=pretrained_model.run_id,
               mode=mfs.DEPLOYMENT_MODE_CREATE)

    s3_client = boto3.client("s3", region_name=region_name)
    default_bucket = mfs._get_default_s3_bucket(region_name)
    object_names_before_replacement = [
            entry["Key"] for entry in s3_client.list_objects(Bucket=default_bucket)["Contents"]]
    endpoint_configs_before_replacement = [
            config["EndpointConfigName"] for config in
            sagemaker_client.list_endpoint_configs()["EndpointConfigs"]]
    models_before_replacement = [
            model["ModelName"] for model in sagemaker_client.list_models()["Models"]]

    sk_model = mlflow.sklearn.load_model(
            path=pretrained_model.model_path, run_id=pretrained_model.run_id)
    new_artifact_path = "model"
    with mlflow.start_run():
        mlflow.sklearn.log_model(sk_model=sk_model, artifact_path=new_artifact_path)
        new_run_id = mlflow.active_run().info.run_uuid
    mfs.deploy(app_name=app_name,
               model_path=new_artifact_path,
               run_id=new_run_id,
               mode=mfs.DEPLOYMENT_MODE_REPLACE,
               archive=True,
               synchronous=True)

    object_names_after_replacement = [
            entry["Key"] for entry in s3_client.list_objects(Bucket=default_bucket)["Contents"]]
    endpoint_configs_after_replacement = [
            config["EndpointConfigName"] for config in
            sagemaker_client.list_endpoint_configs()["EndpointConfigs"]]
    models_after_replacement = [
            model["ModelName"] for model in sagemaker_client.list_models()["Models"]]
    assert all([object_name in object_names_after_replacement
                for object_name in object_names_before_replacement])
    assert all([endpoint_config in endpoint_configs_after_replacement
                for endpoint_config in endpoint_configs_before_replacement])
    assert all([model in models_after_replacement for model in models_before_replacement])
def test_deploy_creates_sagemaker_and_s3_resources_with_expected_names_and_env_from_s3(
        pretrained_model, sagemaker_client):
    local_model_path = _download_artifact_from_uri(pretrained_model.model_uri)
    artifact_path = "model"
    region_name = sagemaker_client.meta.region_name
    default_bucket = mfs._get_default_s3_bucket(region_name)
    s3_artifact_repo = S3ArtifactRepository("s3://{}".format(default_bucket))
    s3_artifact_repo.log_artifacts(local_model_path,
                                   artifact_path=artifact_path)
    model_s3_uri = "s3://{bucket_name}/{artifact_path}".format(
        bucket_name=default_bucket, artifact_path=pretrained_model.model_path)

    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_uri=model_s3_uri,
               mode=mfs.DEPLOYMENT_MODE_CREATE)

    endpoint_description = sagemaker_client.describe_endpoint(
        EndpointName=app_name)
    endpoint_production_variants = endpoint_description["ProductionVariants"]
    assert len(endpoint_production_variants) == 1
    model_name = endpoint_production_variants[0]["VariantName"]
    assert model_name in [
        model["ModelName"]
        for model in sagemaker_client.list_models()["Models"]
    ]

    s3_client = boto3.client("s3", region_name=region_name)
    object_names = [
        entry["Key"]
        for entry in s3_client.list_objects(Bucket=default_bucket)["Contents"]
    ]
    assert any([model_name in object_name for object_name in object_names])
    assert any([
        app_name in config["EndpointConfigName"] for config in
        sagemaker_client.list_endpoint_configs()["EndpointConfigs"]
    ])
    assert app_name in [
        endpoint["EndpointName"]
        for endpoint in sagemaker_client.list_endpoints()["Endpoints"]
    ]
    model_environment = sagemaker_client.describe_model(
        ModelName=model_name)["PrimaryContainer"]["Environment"]
    assert model_environment == {
        "MLFLOW_DEPLOYMENT_FLAVOR_NAME": "python_function",
        "SERVING_ENVIRONMENT": "SageMaker",
    }
Exemple #23
0
def test_deploy_in_replace_mode_waits_for_endpoint_update_completion_before_deleting_resources(
        pretrained_model, sagemaker_client):
    endpoint_update_latency = 10
    sagemaker_backend = get_sagemaker_backend(
        sagemaker_client.meta.region_name)
    sagemaker_backend.set_endpoint_update_latency(endpoint_update_latency)

    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_uri=pretrained_model.model_uri,
               mode=mfs.DEPLOYMENT_MODE_CREATE)
    endpoint_config_name_before_replacement = sagemaker_client.describe_endpoint(
        EndpointName=app_name)["EndpointConfigName"]

    boto_caller = botocore.client.BaseClient._make_api_call
    update_start_time = time.time()

    def validate_deletes(self, operation_name, operation_kwargs):
        """
        Processes all boto3 client operations according to the following rules:
        - If the operation deletes an S3 or SageMaker resource, ensure that the deletion was
          initiated after the completion of the endpoint update
        - Else, execute the client operation as normal
        """
        result = boto_caller(self, operation_name, operation_kwargs)
        if "Delete" in operation_name:
            # Confirm that a successful endpoint update occurred prior to the invocation of this
            # delete operation
            endpoint_info = sagemaker_client.describe_endpoint(
                EndpointName=app_name)
            assert endpoint_info[
                "EndpointStatus"] == Endpoint.STATUS_IN_SERVICE
            assert endpoint_info[
                "EndpointConfigName"] != endpoint_config_name_before_replacement
            assert time.time() - update_start_time >= endpoint_update_latency
        return result

    with mock.patch("botocore.client.BaseClient._make_api_call",
                    new=validate_deletes):
        mfs.deploy(
            app_name=app_name,
            model_uri=pretrained_model.model_uri,
            mode=mfs.DEPLOYMENT_MODE_REPLACE,
            archive=False,
        )
Exemple #24
0
def test_deploy_in_synchronous_mode_waits_for_endpoint_creation_to_complete_before_returning(
        pretrained_model, sagemaker_client):
    endpoint_creation_latency = 10
    get_sagemaker_backend(sagemaker_client.meta.region_name).set_endpoint_update_latency(
        endpoint_creation_latency)

    app_name = "test-app"
    deployment_start_time = time.time()
    mfs.deploy(app_name=app_name,
               model_path=pretrained_model.model_path,
               run_id=pretrained_model.run_id,
               mode=mfs.DEPLOYMENT_MODE_CREATE,
               synchronous=True)
    deployment_end_time = time.time()

    assert (deployment_end_time - deployment_start_time) >= endpoint_creation_latency
    endpoint_description = sagemaker_client.describe_endpoint(EndpointName=app_name)
    assert endpoint_description["EndpointStatus"] == Endpoint.STATUS_IN_SERVICE
Exemple #25
0
def test_deploy_in_replace_model_removes_preexisting_models_from_endpoint(
    pretrained_model, sagemaker_client
):
    app_name = "test-app"
    mfs.deploy(
        app_name=app_name, model_uri=pretrained_model.model_uri, mode=mfs.DEPLOYMENT_MODE_ADD
    )

    for _ in range(11):
        mfs.deploy(
            app_name=app_name,
            model_uri=pretrained_model.model_uri,
            mode=mfs.DEPLOYMENT_MODE_ADD,
            archive=True,
            synchronous=False,
        )

    endpoint_response_before_replacement = sagemaker_client.describe_endpoint(EndpointName=app_name)
    endpoint_config_name_before_replacement = endpoint_response_before_replacement[
        "EndpointConfigName"
    ]
    endpoint_config_response_before_replacement = sagemaker_client.describe_endpoint_config(
        EndpointConfigName=endpoint_config_name_before_replacement
    )
    production_variants_before_replacement = endpoint_config_response_before_replacement[
        "ProductionVariants"
    ]
    deployed_models_before_replacement = [
        variant["ModelName"] for variant in production_variants_before_replacement
    ]

    mfs.deploy(
        app_name=app_name,
        model_uri=pretrained_model.model_uri,
        mode=mfs.DEPLOYMENT_MODE_REPLACE,
        archive=True,
        synchronous=False,
    )

    endpoint_response_after_replacement = sagemaker_client.describe_endpoint(EndpointName=app_name)
    endpoint_config_name_after_replacement = endpoint_response_after_replacement[
        "EndpointConfigName"
    ]
    endpoint_config_response_after_replacement = sagemaker_client.describe_endpoint_config(
        EndpointConfigName=endpoint_config_name_after_replacement
    )
    production_variants_after_replacement = endpoint_config_response_after_replacement[
        "ProductionVariants"
    ]
    deployed_models_after_replacement = [
        variant["ModelName"] for variant in production_variants_after_replacement
    ]
    assert len(deployed_models_after_replacement) == 1
    assert all(
        [
            model_name not in deployed_models_after_replacement
            for model_name in deployed_models_before_replacement
        ]
    )
def deploy_model(app_name,
                 run_id,
                 bucket,
                 tracking_uri,
                 region=get_region(),
                 execution_role_name="mlflow_sagemaker",
                 sagemaker_instance_type=mfs.DEFAULT_SAGEMAKER_INSTANCE_TYPE,
                 sagemaker_instance_count=mfs.DEFAULT_SAGEMAKER_INSTANCE_COUNT,
                 sagemaker_model_mode=mfs.DEPLOYMENT_MODE_CREATE):
    # Verify Model before deploy
    status = check_sagemaker_endpoint_status(app_name=app_name)
    if status and sagemaker_model_mode is mfs.DEPLOYMENT_MODE_CREATE:
        msg = f"AWS Sagemaker endpoint {app_name} exist."
        print(msg)
        raise ValueError(msg)

    run_info = get_mlflow_model_details(run_id, tracking_uri)

    image_ecr_url = get_ecr_url(region=region)
    execution_role_arn = get_sagemager_execution_roler_arn(execution_role_name)
    model_uri = run_info["artifact_uri"] + "/model"

    print(
        f"Model URI is '{model_uri}' for runid '{run_id}' of MlFLow server '{tracking_uri}'"
    )

    mfs.deploy(app_name=app_name,
               execution_role_arn=execution_role_arn,
               bucket=bucket,
               model_uri=model_uri,
               image_url=image_ecr_url,
               region_name=region,
               mode=sagemaker_model_mode,
               instance_type=sagemaker_instance_type,
               instance_count=sagemaker_instance_count)

    run_info['end_point'] = app_name
    print("Model is deployed successfuly on AWS Sagemaker")
    print(f"Model information =>\n{run_info}")
Exemple #27
0
def test_deploy_in_add_mode_adds_new_model_to_existing_endpoint(
        pretrained_model, sagemaker_client):
    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_uri=pretrained_model.model_uri,
               mode=mfs.DEPLOYMENT_MODE_CREATE)
    models_added = 1
    for _ in range(11):
        mfs.deploy(app_name=app_name,
                   model_uri=pretrained_model.model_uri,
                   mode=mfs.DEPLOYMENT_MODE_ADD,
                   archive=True,
                   synchronous=False)
        models_added += 1

    endpoint_response = sagemaker_client.describe_endpoint(
        EndpointName=app_name)
    endpoint_config_name = endpoint_response["EndpointConfigName"]
    endpoint_config_response = sagemaker_client.describe_endpoint_config(
        EndpointConfigName=endpoint_config_name)
    production_variants = endpoint_config_response["ProductionVariants"]
    assert len(production_variants) == models_added
Exemple #28
0
def test_deploy_creates_sagemaker_and_s3_resources_with_expected_names_and_env_from_local(
        pretrained_model, sagemaker_client):
    app_name = "test-app"
    mfs.deploy(app_name=app_name,
               model_uri=pretrained_model.model_uri,
               mode=mfs.DEPLOYMENT_MODE_CREATE)

    region_name = sagemaker_client.meta.region_name
    s3_client = boto3.client("s3", region_name=region_name)
    default_bucket = mfs._get_default_s3_bucket(region_name)
    endpoint_description = sagemaker_client.describe_endpoint(
        EndpointName=app_name)
    endpoint_production_variants = endpoint_description["ProductionVariants"]
    assert len(endpoint_production_variants) == 1
    model_name = endpoint_production_variants[0]["VariantName"]
    assert model_name in [
        model["ModelName"]
        for model in sagemaker_client.list_models()["Models"]
    ]
    object_names = [
        entry["Key"]
        for entry in s3_client.list_objects(Bucket=default_bucket)["Contents"]
    ]
    assert any(model_name in object_name for object_name in object_names)
    assert any(app_name in config["EndpointConfigName"] for config in
               sagemaker_client.list_endpoint_configs()["EndpointConfigs"])
    assert app_name in [
        endpoint["EndpointName"]
        for endpoint in sagemaker_client.list_endpoints()["Endpoints"]
    ]
    model_environment = sagemaker_client.describe_model(
        ModelName=model_name)["PrimaryContainer"]["Environment"]
    assert model_environment == {
        "MLFLOW_DEPLOYMENT_FLAVOR_NAME": "python_function",
        "SERVING_ENVIRONMENT": "SageMaker",
    }
Exemple #29
0
# MAGIC %md
# MAGIC In the cell below we define what we want to call our Sagemaker app, and we get the mlflow image that has been registered to AWS ECR. We use mode "replace" so that we can overwrite our model in subsequent iterations.

# COMMAND ----------

app_name = "xgboostBank"
aws_account_id = "<insert account ID here!>"
aws_region = "<insert AWS ECR region here!>"
repository_name = "<insert ECR repository name here!>"
img_tag = "<insert tage here!>"

# You can also just copy paste the image url from image URI column in ECR UI
image_url = aws_account_id + ".dkr.ecr." + aws_region + ".amazonaws.com/" + repository_name ":" + img_tag

import mlflow.sagemaker as mfs
mfs.deploy(app_name=app_name, model_uri=modelURI, image_url = image_url, region_name="eu-west-1", mode="replace")

# COMMAND ----------

# MAGIC %md
# MAGIC ### Step 3: Querying our deployed model

# COMMAND ----------

df = spark.sql("select * from max_db.bank_marketing_train_set")

# COMMAND ----------

train = df.toPandas()
train_x = train.drop(["label"], axis=1)
sample = train_x.iloc[[0]]
Exemple #30
0
bucket = "sagemaker-us-east-2-" + account_id
image_url = account_id + ".dkr.ecr.us-east-2.amazonaws.com/mckesson"
region = "us-east-2"
mode = mfs.DEPLOYMENT_MODE_CREATE
instance_type = "ml.t2.large"
instance_count = 1
flavor = "python_function"
vpc_config = {
    "SecurityGroupIds": ["sg-0b4cc067"],
    "Subnets": ["subnet-583ff014"]
}

##mlflow sagemaker deploy -a "textcateg" -m "mck_mlflow_pyfunc_linear_1" -e "arn:aws:iam::604136135526:role/service-role/AmazonSageMaker-ExecutionRole-20181123T171117" -b "sagemaker-us-east-2-604136135526" -i "604136135526.dkr.ecr.us-east-2.amazonaws.com/mckesson" --region-name "us-east-2" --mode "create" -t "ml.t2.medium" -c 1 -f "python_function" -v "vpc_config"
mfs.deploy(app_name=app_name,
           model_uri=model_uri,
           execution_role_arn=role_arn,
           bucket=bucket,
           image_url=image_url,
           region_name=region,
           mode=mode,
           archive=False,
           instance_type=instance_type,
           instance_count=instance_count,
           vpc_config=vpc_config,
           flavor=flavor,
           synchronous=True)

print("Deploy completed successfully")

import mlflow.sagemaker as awssmkr
##awssmkr.delete(app_name="textcateg",region_name='us-east-2', archive=False, synchronous=True)