def test_trasformer_pytorch_logger(integration_test_url, project_name, use_google_oauth): merlin.set_url(integration_test_url, use_google_oauth=use_google_oauth) merlin.set_project(project_name) merlin.set_model("transformer-logger", ModelType.PYTORCH) model_dir = "test/transformer" undeploy_all_version() resource_request = ResourceRequest(1, 1, "100m", "200Mi") transformer = Transformer( "gcr.io/kubeflow-ci/kfserving/image-transformer:latest", resource_request=resource_request, ) logger = Logger( model=LoggerConfig(enabled=True, mode=LoggerMode.ALL), transformer=LoggerConfig(enabled=True, mode=LoggerMode.ALL), ) with merlin.new_model_version() as v: merlin.log_pytorch_model(model_dir=model_dir) endpoint = merlin.deploy(transformer=transformer, logger=logger) assert endpoint.logger is not None model_config = endpoint.logger.model assert model_config is not None assert model_config.enabled assert model_config.mode == LoggerMode.ALL transformer_config = endpoint.logger.transformer assert transformer_config is not None assert transformer_config.enabled assert transformer_config.mode == LoggerMode.ALL with open(os.path.join("test/transformer", "input.json"), "r") as f: req = json.load(f) sleep(5) resp = requests.post(f"{endpoint.url}", json=req) assert resp.status_code == 200 assert resp.json() is not None assert len(resp.json()["predictions"]) == len(req["instances"]) model_endpoint = merlin.serve_traffic({endpoint: 100}) sleep(5) resp = requests.post(f"{model_endpoint.url}", json=req) assert resp.status_code == 200 assert resp.json() is not None assert len(resp.json()["predictions"]) == len(req["instances"]) # Try to undeploy serving model version. It must be fail with pytest.raises(Exception): assert merlin.undeploy(v) # Undeploy other running model version endpoints undeploy_all_version()
def test_standard_transformer_with_env_vars(): transformer_config_path = os.path.join("test/transformer", "feast_enricher.yaml") resource = ResourceRequest(min_replica=1, max_replica=2, cpu_request="100m", memory_request="128Mi") transformer = StandardTransformer( config_file=transformer_config_path, enabled=True, resource_request=resource, env_vars={"MODEL_URL": "http://model.default"}) assert transformer.env_vars == { 'MODEL_URL': "http://model.default", 'STANDARD_TRANSFORMER_CONFIG': '{"transformerConfig": {"feast": [{"project": "merlin", "entities": [{"name": "merlin_test_driver_id", "valueType": "STRING", "jsonPath": "$.driver_id"}], "features": [{"name": "merlin_test_driver_features:test_int32", "valueType": "INT32", "defaultValue": "0"}, {"name": "merlin_test_driver_features:test_float", "valueType": "FLOAT", "defaultValue": "0.0"}, {"name": "merlin_test_driver_features:test_double", "valueType": "DOUBLE", "defaultValue": "0.0"}, {"name": "merlin_test_driver_features:test_string", "valueType": "STRING", "defaultValue": ""}]}]}}' } assert transformer.enabled assert transformer.command is None assert transformer.args is None assert transformer.resource_request.min_replica == 1 assert transformer.resource_request.max_replica == 2 assert transformer.resource_request.cpu_request == "100m" assert transformer.resource_request.memory_request == "128Mi" assert transformer.transformer_type == TransformerType.STANDARD_TRANSFORMER
def __init__(self, env: client.Environment): self._name = env.name self._cluster = env.cluster self._is_default = env.is_default self._default_resource_request = ResourceRequest( env.default_resource_request.min_replica, env.default_resource_request.max_replica, env.default_resource_request.cpu_request, env.default_resource_request.memory_request)
def test_custom_model_with_artifact(integration_test_url, project_name, use_google_oauth): merlin.set_url(integration_test_url, use_google_oauth=use_google_oauth) merlin.set_project(project_name) merlin.set_model("custom-w-artifact", ModelType.CUSTOM) undeploy_all_version() resource_request = ResourceRequest(1, 1, "1", "1Gi") model_dir = "test/custom-model" BST_FILE = "model.bst" iris = load_iris() y = iris["target"] X = iris["data"] dtrain = xgb.DMatrix(X, label=y) param = { "max_depth": 6, "eta": 0.1, "silent": 1, "nthread": 4, "num_class": 10, "objective": "multi:softmax", } xgb_model = xgb.train(params=param, dtrain=dtrain) model_file = os.path.join((model_dir), BST_FILE) xgb_model.save_model(model_file) with merlin.new_model_version() as v: v.log_custom_model( image="ghcr.io/tiopramayudi/custom-predictor-go:v0.2", model_dir=model_dir) endpoint = merlin.deploy(v, resource_request=resource_request, env_vars={"MODEL_FILE_NAME": BST_FILE}) sleep(5) resp = requests.post(f"{endpoint.url}", json=request_json) assert resp.status_code == 200 assert resp.json() is not None assert resp.json()["predictions"] is not None model_endpoint = merlin.serve_traffic({endpoint: 100}) sleep(5) resp = requests.post(f"{model_endpoint.url}", json=request_json) assert resp.status_code == 200 assert resp.json() is not None assert resp.json()["predictions"] is not None # Try to undeploy serving model version. It must be fail with pytest.raises(Exception): assert merlin.undeploy(v) # Undeploy other running model version endpoints undeploy_all_version()
def test_resource_request_validate(): resource_request = ResourceRequest(1, 2, "100m", "128Mi") resource_request.validate() resource_request.min_replica = 10 with pytest.raises( Exception, match="Min replica must be less or equal to max replica"): resource_request.validate()
def test_resource_request(integration_test_url, project_name, use_google_oauth): merlin.set_url(integration_test_url, use_google_oauth=use_google_oauth) merlin.set_project(project_name) merlin.set_model("resource-request", ModelType.XGBOOST) model_dir = "test/xgboost-model" BST_FILE = "model.bst" envs = merlin.list_environment() assert len(envs) >= 1 default_env = merlin.get_default_environment() assert default_env is not None undeploy_all_version() with merlin.new_model_version() as v: iris = load_iris() y = iris['target'] X = iris['data'] dtrain = xgb.DMatrix(X, label=y) param = { 'max_depth': 6, 'eta': 0.1, 'silent': 1, 'nthread': 4, 'num_class': 10, 'objective': 'multi:softmax' } xgb_model = xgb.train(params=param, dtrain=dtrain) model_file = os.path.join(model_dir, BST_FILE) xgb_model.save_model(model_file) # Upload the serialized model to MLP merlin.log_model(model_dir=model_dir) resource_request = ResourceRequest(1, 1, "100m", "200Mi") endpoint = merlin.deploy(v, environment_name=default_env.name, resource_request=resource_request) sleep(5) resp = requests.post(f"{endpoint.url}", json=request_json) assert resp.status_code == 200 assert resp.json() is not None assert len(resp.json()['predictions']) == len(request_json['instances']) merlin.undeploy(v) sleep(5) resp = requests.post(f"{endpoint.url}", json=request_json) assert resp.status_code == 404
def test_standard_transformer_with_env_vars(): transformer_config_path = os.path.join("test/transformer", "feast_standard_transformer.yaml") resource = ResourceRequest(min_replica=1, max_replica=2, cpu_request="100m", memory_request="128Mi") transformer = StandardTransformer(config_file=transformer_config_path, enabled=True, resource_request=resource, env_vars={"MODEL_URL": "http://model.default"}) assert transformer.env_vars == {'MODEL_URL': "http://model.default", 'STANDARD_TRANSFORMER_CONFIG': '{"transformerConfig": {"feast": [{"entities": [{"name": "customer_id", "valueType": "STRING", "jsonPath": "$.customer_id"}], "features": [{"name": "total_booking_1w", "defaultValue": "0.0"}, {"name": "total_booking_4w", "defaultValue": "0.0"}]}, {"entities": [{"name": "merchant_id", "valueType": "STRING", "jsonPath": "$.merchant_id"}], "features": [{"name": "total_completed_order_1w", "defaultValue": "0.0"}, {"name": "avg_completed_order_1w", "defaultValue": "0.0"}]}]}}'} assert transformer.enabled assert transformer.command is None assert transformer.args is None assert transformer.resource_request.min_replica == 1 assert transformer.resource_request.max_replica == 2 assert transformer.resource_request.cpu_request == "100m" assert transformer.resource_request.memory_request == "128Mi" assert transformer.transformer_type == TransformerType.STANDARD_TRANSFORMER
def test_xgboost(integration_test_url, project_name, use_google_oauth): merlin.set_url(integration_test_url, use_google_oauth=use_google_oauth) merlin.set_project(project_name) merlin.set_model("xgboost-sample", ModelType.XGBOOST) model_dir = "test/xgboost-model" BST_FILE = "model.bst" undeploy_all_version() with merlin.new_model_version() as v: iris = load_iris() y = iris["target"] X = iris["data"] dtrain = xgb.DMatrix(X, label=y) param = { "max_depth": 6, "eta": 0.1, "silent": 1, "nthread": 4, "num_class": 10, "objective": "multi:softmax", } xgb_model = xgb.train(params=param, dtrain=dtrain) model_file = os.path.join(model_dir, BST_FILE) xgb_model.save_model(model_file) # Upload the serialized model to MLP merlin.log_model(model_dir=model_dir) resource_request = ResourceRequest(1, 1, "100m", "200Mi") endpoint = merlin.deploy(v, resource_request=resource_request) resp = requests.post(f"{endpoint.url}", json=request_json) assert resp.status_code == 200 assert resp.json() is not None assert len(resp.json()["predictions"]) == len(request_json["instances"]) merlin.undeploy(v)
def test_custom_model_without_artifact(integration_test_url, project_name, use_google_oauth): merlin.set_url(integration_test_url, use_google_oauth=use_google_oauth) merlin.set_project(project_name) merlin.set_model("custom-wo-artifact", ModelType.CUSTOM) undeploy_all_version() resource_request = ResourceRequest(1, 1, "1", "1Gi") with merlin.new_model_version() as v: v.log_custom_model(image="ghcr.io/tiopramayudi/custom-predictor:v0.2") endpoint = merlin.deploy(v, resource_request=resource_request) with open(os.path.join("test/custom-model", "input.json"), "r") as f: req = json.load(f) sleep(5) resp = requests.post(f"{endpoint.url}", json=req) assert resp.status_code == 200 assert resp.json() is not None assert resp.json()["predictions"] is not None model_endpoint = merlin.serve_traffic({endpoint: 100}) sleep(5) resp = requests.post(f"{model_endpoint.url}", json=req) assert resp.status_code == 200 assert resp.json() is not None assert resp.json()["predictions"] is not None # Try to undeploy serving model version. It must be fail with pytest.raises(Exception): assert merlin.undeploy(v) # Undeploy other running model version endpoints undeploy_all_version()