From 116fb225353d7783de1bc92497827e4f6f758066 Mon Sep 17 00:00:00 2001 From: Anubhav Sachan Date: Mon, 15 Aug 2022 13:14:39 -0700 Subject: [PATCH 01/10] Feature: Support multiple inference.py files and universal inference.py file along with universal requirements.txt file --- README.md | 17 +- .../sagemaker/python_service.py | 36 +++- docker/build_artifacts/sagemaker/serve.py | 10 +- ...me.py => test_pre_post_processing_mme1.py} | 87 +++++---- .../local/test_pre_post_processing_mme2.py | 175 +++++++++++++++++ .../local/test_pre_post_processing_mme3.py | 176 +++++++++++++++++ .../local/test_pre_post_processing_mme4.py | 178 ++++++++++++++++++ .../code/inference.py | 0 .../code/requirements.txt | 0 .../half_plus_three/00000123/assets/foo.txt | 0 .../half_plus_three/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../half_plus_three/00000124/assets/foo.txt | 0 .../half_plus_three/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../half_plus_two/00000123/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000124/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes test/resources/mme2/code/inference.py | 29 +++ test/resources/mme2/code/requirements.txt | 1 + .../half_plus_three/model/code/inference.py | 58 ++++++ .../half_plus_three/00000123/assets/foo.txt | 1 + .../half_plus_three/00000123/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_three/00000124/assets/foo.txt | 1 + .../half_plus_three/00000124/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/model/code/inference.py | 59 ++++++ .../half_plus_two/00000123/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000124/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes test/resources/mme3/code/inference.py | 70 +++++++ .../mme3/code/lib/dummy_module/__init__.py | 1 + test/resources/mme3/code/requirements.txt | 1 + .../half_plus_three/model/code/inference.py | 69 +++++++ .../model/code/lib/dummy_module/__init__.py | 1 + .../half_plus_three/00000123/assets/foo.txt | 1 + .../half_plus_three/00000123/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_three/00000124/assets/foo.txt | 1 + .../half_plus_three/00000124/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000123/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000124/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_three/model/code/inference.py | 75 ++++++++ .../model/code/lib/dummy_module/__init__.py | 1 + .../half_plus_three/00000123/assets/foo.txt | 1 + .../half_plus_three/00000123/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_three/00000124/assets/foo.txt | 1 + .../half_plus_three/00000124/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000123/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000124/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes 76 files changed, 1002 insertions(+), 48 deletions(-) rename test/integration/local/{test_pre_post_processing_mme.py => test_pre_post_processing_mme1.py} (55%) create mode 100644 test/integration/local/test_pre_post_processing_mme2.py create mode 100644 test/integration/local/test_pre_post_processing_mme3.py create mode 100644 test/integration/local/test_pre_post_processing_mme4.py rename test/resources/{mme_universal_script => mme1}/code/inference.py (100%) rename test/resources/{mme_universal_script => mme1}/code/requirements.txt (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000123/assets/foo.txt (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000123/saved_model.pb (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000123/variables/variables.index (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000124/assets/foo.txt (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000124/saved_model.pb (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000124/variables/variables.index (100%) create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000123/saved_model.pb create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.index create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000124/saved_model.pb create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.index create mode 100644 test/resources/mme2/code/inference.py create mode 100644 test/resources/mme2/code/requirements.txt create mode 100644 test/resources/mme2/half_plus_three/model/code/inference.py create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000123/saved_model.pb create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.index create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000124/saved_model.pb create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.index create mode 100644 test/resources/mme2/half_plus_two/model/code/inference.py create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000123/saved_model.pb create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.index create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000124/saved_model.pb create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.index create mode 100644 test/resources/mme3/code/inference.py create mode 100644 test/resources/mme3/code/lib/dummy_module/__init__.py create mode 100644 test/resources/mme3/code/requirements.txt create mode 100644 test/resources/mme3/half_plus_three/model/code/inference.py create mode 100644 test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000123/saved_model.pb create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.index create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000124/saved_model.pb create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.index create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000123/saved_model.pb create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.index create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000124/saved_model.pb create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.index create mode 100644 test/resources/mme4/half_plus_three/model/code/inference.py create mode 100644 test/resources/mme4/half_plus_three/model/code/lib/dummy_module/__init__.py create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000123/assets/foo.txt create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000123/saved_model.pb create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.index create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000124/saved_model.pb create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.index create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000123/saved_model.pb create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.index create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000124/saved_model.pb create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.index diff --git a/README.md b/README.md index 8447474f..e8042719 100644 --- a/README.md +++ b/README.md @@ -164,8 +164,6 @@ For example: ## Pre/Post-Processing -**NOTE: There is currently no support for pre-/post-processing with multi-model containers.** - SageMaker TensorFlow Serving Container supports the following Content-Types for requests: * `application/json` (default) @@ -672,7 +670,7 @@ Only 90% of the ports will be utilized and each loaded model will be allocated w For example, if the ``SAGEMAKER_SAFE_PORT_RANGE`` is between 9000 to 9999, the maximum number of models that can be loaded to the endpoint at the same time would be 499 ((9999 - 9000) * 0.9 / 2). ### Using Multi-Model Endpoint with Pre/Post-Processing -Multi-Model Endpoint can be used together with Pre/Post-Processing. Each model will need its own ``inference.py`` otherwise default handlers will be used. An example of the directory structure of Multi-Model Endpoint and Pre/Post-Processing would look like this: +Multi-Model Endpoint can be used together with Pre/Post-Processing. Each model can either have its own ``inference.py`` or use a universal ``inference.py``. If both model-specific and universal ``inference.py`` files are provided, then the model-specific ``inference.py`` file is used. If both files are absent, then the default handlers will be used. An example of the directory structure of Multi-Model Endpoint with a model-specific ``inference.py`` file would look like this: /opt/ml/models/model1/model |--[model_version_number] @@ -687,7 +685,20 @@ Multi-Model Endpoint can be used together with Pre/Post-Processing. Each model w |--lib |--external_module |--inference.py +Another example with of the directory structure of Multi-Model Endpoint with a universal ``inference.py`` file is as follows: + /opt/ml/models/model1/model + |--[model_version_number] + |--variables + |--saved_model.pb + /opt/ml/models/model2/model + |--[model_version_number] + |--assets + |--variables + |--saved_model.pb + code + |--requirements.txt + |--inference.py ## Contributing Please read [CONTRIBUTING.md](https://github.com/aws/sagemaker-tensorflow-serving-container/blob/master/CONTRIBUTING.md) diff --git a/docker/build_artifacts/sagemaker/python_service.py b/docker/build_artifacts/sagemaker/python_service.py index fd9954cc..1a8f7021 100644 --- a/docker/build_artifacts/sagemaker/python_service.py +++ b/docker/build_artifacts/sagemaker/python_service.py @@ -17,6 +17,7 @@ import os import subprocess import grpc +import sys import falcon import requests @@ -26,7 +27,7 @@ import tfs_utils SAGEMAKER_MULTI_MODEL_ENABLED = os.environ.get("SAGEMAKER_MULTI_MODEL", "false").lower() == "true" -MODEL_DIR = "models" if SAGEMAKER_MULTI_MODEL_ENABLED else "model" +MODEL_DIR = "" if SAGEMAKER_MULTI_MODEL_ENABLED else "model" INFERENCE_SCRIPT_PATH = f"/opt/ml/{MODEL_DIR}/code/inference.py" SAGEMAKER_BATCHING_ENABLED = os.environ.get("SAGEMAKER_TFS_ENABLE_BATCHING", "false").lower() @@ -77,6 +78,7 @@ def __init__(self): # between each grpc port and channel self._setup_channel(grpc_port) + self._default_handlers_enabled = False if os.path.exists(INFERENCE_SCRIPT_PATH): # Single-Model Mode & Multi-Model Mode both use one inference.py self._handler, self._input_handler, self._output_handler = self._import_handlers() @@ -85,6 +87,7 @@ def __init__(self): ) else: self._handlers = default_handler + self._default_handlers_enabled = True self._tfs_enable_batching = SAGEMAKER_BATCHING_ENABLED == "true" self._tfs_default_model_name = os.environ.get("TFS_DEFAULT_MODEL_NAME", "None") @@ -143,6 +146,7 @@ def _handle_load_model_post(self, res, data): # noqa: C901 # validate model files are in the specified base_path if self.validate_model_dir(base_path): try: + self._import_custom_modules(model_name) tfs_config = tfs_utils.create_tfs_config_individual_model(model_name, base_path) tfs_config_file = "/sagemaker/tfs-config/{}/model-config.cfg".format(model_name) log.info("tensorflow serving model config: \n%s\n", tfs_config) @@ -221,6 +225,17 @@ def _handle_load_model_post(self, res, data): # noqa: C901 } ) + def _import_custom_modules(self, model_name): + inference_script_path = "/opt/ml/models/{}/model/code/inference.py".format(model_name) + python_lib_path = "/opt/ml/models/{}/model/code/lib".format(model_name) + if os.path.exists(python_lib_path): + log.info("add Python code library path") + sys.path.append(python_lib_path) + if os.path.exists(inference_script_path): + handler, input_handler, output_handler = self._import_handlers(inference_script_path) + model_handlers = self._make_handler(handler, input_handler, output_handler) + self.model_handlers[model_name] = model_handlers + def _cleanup_config_file(self, config_file): if os.path.exists(config_file): os.remove(config_file) @@ -264,8 +279,20 @@ def _handle_invocation_post(self, req, res, model_name=None): try: res.status = falcon.HTTP_200 - - res.body, res.content_type = self._handlers(data, context) + handlers = self._handlers + if SAGEMAKER_MULTI_MODEL_ENABLED and model_name in self.model_handlers: + inference_script_path = "/opt/ml/models/{}/model/code/" \ + "inference.py".format(model_name) + log.info("Inference script found at path {}.".format(inference_script_path)) + log.info("Inference script exists, importing handlers.") + handlers = self.model_handlers[model_name] + elif not self._default_handlers_enabled: + log.info("Universal inference script found at path " + "{}.".format(INFERENCE_SCRIPT_PATH)) + log.info("Universal inference script exists, importing handlers.") + else: + log.info("Inference script does not exist, using default handlers.") + res.body, res.content_type = handlers(data, context) except Exception as e: # pylint: disable=broad-except log.exception("exception handling request: {}".format(e)) res.status = falcon.HTTP_500 @@ -276,8 +303,7 @@ def _setup_channel(self, grpc_port): log.info("Creating grpc channel for port: %s", grpc_port) self._channels[grpc_port] = grpc.insecure_channel("localhost:{}".format(grpc_port)) - def _import_handlers(self): - inference_script = INFERENCE_SCRIPT_PATH + def _import_handlers(self, inference_script=INFERENCE_SCRIPT_PATH): spec = importlib.util.spec_from_file_location("inference", inference_script) inference = importlib.util.module_from_spec(spec) spec.loader.exec_module(inference) diff --git a/docker/build_artifacts/sagemaker/serve.py b/docker/build_artifacts/sagemaker/serve.py index e5461346..ef885529 100644 --- a/docker/build_artifacts/sagemaker/serve.py +++ b/docker/build_artifacts/sagemaker/serve.py @@ -28,9 +28,8 @@ JS_INVOCATIONS = "js_content tensorflowServing.invocations" GUNICORN_PING = "proxy_pass http://gunicorn_upstream/ping" GUNICORN_INVOCATIONS = "proxy_pass http://gunicorn_upstream/invocations" -MULTI_MODEL = "s" if os.environ.get("SAGEMAKER_MULTI_MODEL", "False").lower() == "true" else "" -MODEL_DIR = f"model{MULTI_MODEL}" -CODE_DIR = "/opt/ml/{}/code".format(MODEL_DIR) +MODEL_DIR = "" if os.environ.get("SAGEMAKER_MULTI_MODEL", "False").lower() == "true" else "model" +CODE_DIR = f"/opt/ml/{MODEL_DIR}/code" PYTHON_LIB_PATH = os.path.join(CODE_DIR, "lib") REQUIREMENTS_PATH = os.path.join(CODE_DIR, "requirements.txt") INFERENCE_PATH = os.path.join(CODE_DIR, "inference.py") @@ -134,7 +133,8 @@ def __init__(self): os.environ["TFS_REST_PORTS"] = self._tfs_rest_concat_ports def _need_python_service(self): - if os.path.exists(INFERENCE_PATH): + if (os.path.exists(INFERENCE_PATH) or os.path.exists(REQUIREMENTS_PATH) + or os.path.exists(PYTHON_LIB_PATH)): self._enable_python_service = True if os.environ.get("SAGEMAKER_MULTI_MODEL_UNIVERSAL_BUCKET") and os.environ.get( "SAGEMAKER_MULTI_MODEL_UNIVERSAL_PREFIX" @@ -256,7 +256,7 @@ def _download_scripts(self, bucket, prefix): paginator = client.get_paginator("list_objects") for result in paginator.paginate(Bucket=bucket, Delimiter="/", Prefix=prefix): for file in result.get("Contents", []): - destination = os.path.join(CODE_DIR, file.get("Key")) + destination = os.path.join(CODE_DIR, file.get("Key").split("/")[-1]) if not os.path.exists(os.path.dirname(destination)): os.makedirs(os.path.dirname(destination)) resource.meta.client.download_file(bucket, file.get("Key"), destination) diff --git a/test/integration/local/test_pre_post_processing_mme.py b/test/integration/local/test_pre_post_processing_mme1.py similarity index 55% rename from test/integration/local/test_pre_post_processing_mme.py rename to test/integration/local/test_pre_post_processing_mme1.py index 5eb0fb6e..8b125d19 100644 --- a/test/integration/local/test_pre_post_processing_mme.py +++ b/test/integration/local/test_pre_post_processing_mme1.py @@ -11,9 +11,11 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +# In this test, only a universal inference.py file is provided. It's expected the handlers from the universal +# inference.py file should be used by both models. + import json import os -import shutil import subprocess import sys import time @@ -27,19 +29,19 @@ PING_URL = "http://localhost:8080/ping" INVOCATION_URL = "http://localhost:8080/models/{}/invoke" -MODEL_NAME = "half_plus_three" +MODEL_NAMES = ["half_plus_three","half_plus_two"] @pytest.fixture(scope="session", autouse=True) def volume(): try: - model_dir = os.path.abspath("test/resources/mme_universal_script") + model_dir = os.path.abspath("test/resources/mme1") subprocess.check_call( - "docker volume create --name model_volume_mme --opt type=none " + "docker volume create --name model_volume_mme1 --opt type=none " "--opt device={} --opt o=bind".format(model_dir).split()) yield model_dir finally: - subprocess.check_call("docker volume rm model_volume_mme".split()) + subprocess.check_call("docker volume rm model_volume_mme1".split()) @pytest.fixture(scope="module", autouse=True) @@ -47,7 +49,7 @@ def container(docker_base_name, tag, runtime_config): try: command = ( "docker run {}--name sagemaker-tensorflow-serving-test -p 8080:8080" - " --mount type=volume,source=model_volume_mme,target=/opt/ml/models,readonly" + " --mount type=volume,source=model_volume_mme1,target=/opt/ml/models,readonly" " -e SAGEMAKER_TFS_NGINX_LOGLEVEL=info" " -e SAGEMAKER_BIND_TO_PORT=8080" " -e SAGEMAKER_SAFE_PORT_RANGE=9000-9999" @@ -74,13 +76,14 @@ def container(docker_base_name, tag, runtime_config): @pytest.fixture -def model(): - model_data = { - "model_name": MODEL_NAME, - "url": "/opt/ml/models/half_plus_three/model/half_plus_three" - } - make_load_model_request(json.dumps(model_data)) - return MODEL_NAME +def models(): + for MODEL_NAME in MODEL_NAMES: + model_data = { + "model_name": MODEL_NAME, + "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + } + make_load_model_request(json.dumps(model_data)) + return MODEL_NAMES @pytest.mark.skip_gpu @@ -90,20 +93,25 @@ def test_ping_service(): @pytest.mark.skip_gpu -def test_predict_json(model): +def test_predict_json(models): headers = make_headers() data = "{\"instances\": [1.0, 2.0, 5.0]}" - response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() - assert response == {"predictions": [3.5, 4.0, 5.5]} + responses = [] + for model in models: + response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} @pytest.mark.skip_gpu def test_zero_content(): headers = make_headers() x = "" - response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) - assert 500 == response.status_code - assert "document is empty" in response.text + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) + assert 500 == response.status_code + assert "document is empty" in response.text @pytest.mark.skip_gpu @@ -113,34 +121,43 @@ def test_large_input(): with open(data_file, "r") as file: x = file.read() headers = make_headers(content_type="text/csv") - response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() - predictions = response["predictions"] - assert len(predictions) == 753936 + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() + predictions = response["predictions"] + assert len(predictions) == 753936 @pytest.mark.skip_gpu def test_csv_input(): headers = make_headers(content_type="text/csv") data = "1.0,2.0,5.0" - response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() - assert response == {"predictions": [3.5, 4.0, 5.5]} - + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} @pytest.mark.skip_gpu def test_specific_versions(): - for version in ("123", "124"): - headers = make_headers(content_type="text/csv", version=version) - data = "1.0,2.0,5.0" - response = requests.post( - INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers - ).json() - assert response == {"predictions": [3.5, 4.0, 5.5]} + for MODEL_NAME in MODEL_NAMES: + for version in ("123", "124"): + headers = make_headers(content_type="text/csv", version=version) + data = "1.0,2.0,5.0" + response = requests.post( + INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers + ).json() + if MODEL_NAME == "half_plus_three": + assert response == {"predictions": [3.5, 4.0, 5.5]} + else: + assert response == {"predictions": [2.5, 3.0, 4.5]} @pytest.mark.skip_gpu def test_unsupported_content_type(): headers = make_headers("unsupported-type", "predict") data = "aW1hZ2UgYnl0ZXM=" - response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) - assert 500 == response.status_code - assert "unsupported content type" in response.text + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) + assert 500 == response.status_code + assert "unsupported content type" in response.text diff --git a/test/integration/local/test_pre_post_processing_mme2.py b/test/integration/local/test_pre_post_processing_mme2.py new file mode 100644 index 00000000..4c52d219 --- /dev/null +++ b/test/integration/local/test_pre_post_processing_mme2.py @@ -0,0 +1,175 @@ +# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +# The model-specific inference.py files for both models and the universal inference.py file are provided. It is +# expected that the handlers from the model-specific inference.py files should be used and the handlers from the +# universal inference.py file should be ignored. + +import json +import os +import subprocess +import sys +import time + +import pytest + +import requests + +from multi_model_endpoint_test_utils import make_load_model_request, make_headers + + +PING_URL = "http://localhost:8080/ping" +INVOCATION_URL = "http://localhost:8080/models/{}/invoke" +MODEL_NAMES = ["half_plus_three","half_plus_two"] + + +@pytest.fixture(scope="session", autouse=True) +def volume(): + try: + model_dir = os.path.abspath("test/resources/mme2") + subprocess.check_call( + "docker volume create --name model_volume_mme2 --opt type=none " + "--opt device={} --opt o=bind".format(model_dir).split()) + yield model_dir + finally: + subprocess.check_call("docker volume rm model_volume_mme2".split()) + + +@pytest.fixture(scope="module", autouse=True) +def container(docker_base_name, tag, runtime_config): + try: + command = ( + "docker run {}--name sagemaker-tensorflow-serving-test -p 8080:8080" + " --mount type=volume,source=model_volume_mme2,target=/opt/ml/models,readonly" + " -e SAGEMAKER_TFS_NGINX_LOGLEVEL=info" + " -e SAGEMAKER_BIND_TO_PORT=8080" + " -e SAGEMAKER_SAFE_PORT_RANGE=9000-9999" + " -e SAGEMAKER_MULTI_MODEL=True" + " {}:{} serve" + ).format(runtime_config, docker_base_name, tag) + + proc = subprocess.Popen(command.split(), stdout=sys.stdout, stderr=subprocess.STDOUT) + + attempts = 0 + while attempts < 40: + time.sleep(3) + try: + res_code = requests.get("http://localhost:8080/ping").status_code + if res_code == 200: + break + except: + attempts += 1 + pass + + yield proc.pid + finally: + subprocess.check_call("docker rm -f sagemaker-tensorflow-serving-test".split()) + + +@pytest.fixture +def models(): + for MODEL_NAME in MODEL_NAMES: + model_data = { + "model_name": MODEL_NAME, + "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + } + make_load_model_request(json.dumps(model_data)) + return MODEL_NAMES + + +@pytest.mark.skip_gpu +def test_ping_service(): + response = requests.get(PING_URL) + assert 200 == response.status_code + + +@pytest.mark.skip_gpu +def test_predict_json(models): + headers = make_headers() + data = "{\"instances\": [1.0, 2.0, 5.0]}" + responses = [] + for model in models: + response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + error = responses[1]["error"] + assert "unsupported content type application/json" in error + + +@pytest.mark.skip_gpu +def test_zero_content(): + headers = make_headers() + x = "" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) + responses.append(response) + print(MODEL_NAME,response) + assert 500 == responses[0].status_code + assert "document is empty" in responses[0].text + assert 500 == responses[1].status_code + assert "unsupported content type application/json" in responses[1].text + + +@pytest.mark.skip_gpu +def test_large_input(): + data_file = "test/resources/inputs/test-large.csv" + + with open(data_file, "r") as file: + x = file.read() + headers = make_headers(content_type="text/csv") + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() + responses.append(response) + error = responses[0]["error"] + assert "unsupported content type text/csv" in error + predictions = responses[1]["predictions"] + assert len(predictions) == 753936 + + +@pytest.mark.skip_gpu +def test_csv_input(): + headers = make_headers(content_type="text/csv") + data = "1.0,2.0,5.0" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() + responses.append(response) + error = responses[0]["error"] + assert "unsupported content type text/csv" in error + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} + +@pytest.mark.skip_gpu +def test_specific_versions(): + for MODEL_NAME in MODEL_NAMES: + for version in ("123", "124"): + headers = make_headers(content_type="text/csv", version=version) + data = "1.0,2.0,5.0" + response = requests.post( + INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers + ).json() + if MODEL_NAME == "half_plus_three": + error = response["error"] + assert "unsupported content type text/csv" in error + else: + assert response == {"predictions": [2.5, 3.0, 4.5]} + +@pytest.mark.skip_gpu +def test_unsupported_content_type(): + headers = make_headers("unsupported-type", "predict") + data = "aW1hZ2UgYnl0ZXM=" + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) + assert 500 == response.status_code + assert "unsupported content type" in response.text diff --git a/test/integration/local/test_pre_post_processing_mme3.py b/test/integration/local/test_pre_post_processing_mme3.py new file mode 100644 index 00000000..99b5d407 --- /dev/null +++ b/test/integration/local/test_pre_post_processing_mme3.py @@ -0,0 +1,176 @@ +# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +# A model-specific inference.py file for the model half_plus_three and a universal inference.py file are provided. A +# specific inference.py file for the model half_plus_two is not provided. It is expected that the handlers from the +# model-specific inference.py file should be used for the model half_plus_three and the handlers from the universal +# inference.py file should be used for the model half_plus_two. +import json +import os +import subprocess +import sys +import time + +import pytest + +import requests + +from multi_model_endpoint_test_utils import make_load_model_request, make_headers + + +PING_URL = "http://localhost:8080/ping" +INVOCATION_URL = "http://localhost:8080/models/{}/invoke" +MODEL_NAMES = ["half_plus_three","half_plus_two"] + + +@pytest.fixture(scope="session", autouse=True) +def volume(): + try: + model_dir = os.path.abspath("test/resources/mme3") + subprocess.check_call( + "docker volume create --name model_volume_mme3 --opt type=none " + "--opt device={} --opt o=bind".format(model_dir).split()) + yield model_dir + finally: + subprocess.check_call("docker volume rm model_volume_mme3".split()) + + +@pytest.fixture(scope="module", autouse=True) +def container(docker_base_name, tag, runtime_config): + try: + command = ( + "docker run {}--name sagemaker-tensorflow-serving-test -p 8080:8080" + " --mount type=volume,source=model_volume_mme3,target=/opt/ml/models,readonly" + " -e SAGEMAKER_TFS_NGINX_LOGLEVEL=info" + " -e SAGEMAKER_BIND_TO_PORT=8080" + " -e SAGEMAKER_SAFE_PORT_RANGE=9000-9999" + " -e SAGEMAKER_MULTI_MODEL=True" + " {}:{} serve" + ).format(runtime_config, docker_base_name, tag) + + proc = subprocess.Popen(command.split(), stdout=sys.stdout, stderr=subprocess.STDOUT) + + attempts = 0 + while attempts < 40: + time.sleep(3) + try: + res_code = requests.get("http://localhost:8080/ping").status_code + if res_code == 200: + break + except: + attempts += 1 + pass + + yield proc.pid + finally: + subprocess.check_call("docker rm -f sagemaker-tensorflow-serving-test".split()) + + +@pytest.fixture +def models(): + for MODEL_NAME in MODEL_NAMES: + model_data = { + "model_name": MODEL_NAME, + "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + } + make_load_model_request(json.dumps(model_data)) + return MODEL_NAMES + + +@pytest.mark.skip_gpu +def test_ping_service(): + response = requests.get(PING_URL) + assert 200 == response.status_code + + +@pytest.mark.skip_gpu +def test_predict_json(models): + headers = make_headers() + data = "{\"instances\": [1.0, 2.0, 5.0]}" + responses = [] + for model in models: + response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + error = responses[1]["error"] + assert "unsupported content type application/json" in error + + +@pytest.mark.skip_gpu +def test_zero_content(): + headers = make_headers() + x = "" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) + responses.append(response) + print(MODEL_NAME,response) + assert 500 == responses[0].status_code + assert "document is empty" in responses[0].text + assert 500 == responses[1].status_code + assert "unsupported content type application/json" in responses[1].text + + +@pytest.mark.skip_gpu +def test_large_input(): + data_file = "test/resources/inputs/test-large.csv" + + with open(data_file, "r") as file: + x = file.read() + headers = make_headers(content_type="text/csv") + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() + responses.append(response) + error = responses[0]["error"] + assert "unsupported content type text/csv" in error + predictions = responses[1]["predictions"] + assert len(predictions) == 753936 + + +@pytest.mark.skip_gpu +def test_csv_input(): + headers = make_headers(content_type="text/csv") + data = "1.0,2.0,5.0" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() + responses.append(response) + error = responses[0]["error"] + assert "unsupported content type text/csv" in error + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} + +@pytest.mark.skip_gpu +def test_specific_versions(): + for MODEL_NAME in MODEL_NAMES: + for version in ("123", "124"): + headers = make_headers(content_type="text/csv", version=version) + data = "1.0,2.0,5.0" + response = requests.post( + INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers + ).json() + if MODEL_NAME == "half_plus_three": + error = response["error"] + assert "unsupported content type text/csv" in error + else: + assert response == {"predictions": [2.5, 3.0, 4.5]} + + +@pytest.mark.skip_gpu +def test_unsupported_content_type(): + headers = make_headers("unsupported-type", "predict") + data = "aW1hZ2UgYnl0ZXM=" + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) + assert 500 == response.status_code + assert "unsupported content type" in response.text diff --git a/test/integration/local/test_pre_post_processing_mme4.py b/test/integration/local/test_pre_post_processing_mme4.py new file mode 100644 index 00000000..7ce41150 --- /dev/null +++ b/test/integration/local/test_pre_post_processing_mme4.py @@ -0,0 +1,178 @@ +# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +# Only a model-specific inference.py file for the model half_plus_three is provided. Neither a specific inference.py +# file for the model half_plus_two nor a universal inference.py file is provided. It is expected that the handlers +# from the model-specific inference.py file should be used for the model half_plus_three and the default handlers +# should be used for the model half_plus_two. +import json +import os +import subprocess +import sys +import time + +import pytest + +import requests + +from multi_model_endpoint_test_utils import make_load_model_request, make_headers + + +PING_URL = "http://localhost:8080/ping" +INVOCATION_URL = "http://localhost:8080/models/{}/invoke" +MODEL_NAMES = ["half_plus_three","half_plus_two"] + + +@pytest.fixture(scope="session", autouse=True) +def volume(): + try: + model_dir = os.path.abspath("test/resources/mme4") + subprocess.check_call( + "docker volume create --name model_volume_mme4 --opt type=none " + "--opt device={} --opt o=bind".format(model_dir).split()) + yield model_dir + finally: + subprocess.check_call("docker volume rm model_volume_mme4".split()) + + +@pytest.fixture(scope="module", autouse=True) +def container(docker_base_name, tag, runtime_config): + try: + command = ( + "docker run {}--name sagemaker-tensorflow-serving-test -p 8080:8080" + " --mount type=volume,source=model_volume_mme4,target=/opt/ml/models,readonly" + " -e SAGEMAKER_TFS_NGINX_LOGLEVEL=info" + " -e SAGEMAKER_BIND_TO_PORT=8080" + " -e SAGEMAKER_SAFE_PORT_RANGE=9000-9999" + " -e SAGEMAKER_MULTI_MODEL=True" + " {}:{} serve" + ).format(runtime_config, docker_base_name, tag) + + proc = subprocess.Popen(command.split(), stdout=sys.stdout, stderr=subprocess.STDOUT) + + attempts = 0 + while attempts < 40: + time.sleep(3) + try: + res_code = requests.get("http://localhost:8080/ping").status_code + if res_code == 200: + break + except: + attempts += 1 + pass + + yield proc.pid + finally: + subprocess.check_call("docker rm -f sagemaker-tensorflow-serving-test".split()) + + +@pytest.fixture +def models(): + for MODEL_NAME in MODEL_NAMES: + model_data = { + "model_name": MODEL_NAME, + "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + } + make_load_model_request(json.dumps(model_data)) + return MODEL_NAMES + + +@pytest.mark.skip_gpu +def test_ping_service(): + response = requests.get(PING_URL) + assert 200 == response.status_code + + +@pytest.mark.skip_gpu +def test_predict_json(models): + headers = make_headers() + data = "{\"instances\": [1.0, 2.0, 5.0]}" + responses = [] + for model in models: + response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} + + +@pytest.mark.skip_gpu +def test_zero_content(): + headers = make_headers() + x = "" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) + responses.append(response) + print(MODEL_NAME,response) + assert 500 == responses[0].status_code + assert "document is empty" in responses[0].text + assert 200 == responses[1].status_code + assert "document is empty" in responses[1].text + + +@pytest.mark.skip_gpu +def test_large_input(): + data_file = "test/resources/inputs/test-large.csv" + + with open(data_file, "r") as file: + x = file.read() + headers = make_headers(content_type="text/csv") + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() + responses.append(response) + predictions = responses[0]["predictions"] + assert len(predictions) == 753936 + error = responses[1]["error"] + assert "document root must not be followed by other values" in error + + +@pytest.mark.skip_gpu +def test_csv_input(): + headers = make_headers(content_type="text/csv") + data = "1.0,2.0,5.0" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + error = responses[1]["error"] + assert "document root must not be followed by other values" in error + +@pytest.mark.skip_gpu +def test_specific_versions(): + for MODEL_NAME in MODEL_NAMES: + for version in ("123", "124"): + headers = make_headers(content_type="text/csv", version=version) + data = "1.0,2.0,5.0" + response = requests.post( + INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers + ).json() + if MODEL_NAME == 'half_plus_three': + assert response == {"predictions": [3.5, 4.0, 5.5]} + else: + error = response["error"] + assert "document root must not be followed by other values" in error + +@pytest.mark.skip_gpu +def test_unsupported_content_type(): + headers = make_headers("unsupported-type", "predict") + data = "aW1hZ2UgYnl0ZXM=" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) + responses.append(response) + assert 500 == responses[0].status_code + assert "unsupported content type" in responses[0].text + assert 200 == responses[1].status_code + assert "Invalid value" in responses[1].text diff --git a/test/resources/mme_universal_script/code/inference.py b/test/resources/mme1/code/inference.py similarity index 100% rename from test/resources/mme_universal_script/code/inference.py rename to test/resources/mme1/code/inference.py diff --git a/test/resources/mme_universal_script/code/requirements.txt b/test/resources/mme1/code/requirements.txt similarity index 100% rename from test/resources/mme_universal_script/code/requirements.txt rename to test/resources/mme1/code/requirements.txt diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/assets/foo.txt rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000123/assets/foo.txt diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/saved_model.pb similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/saved_model.pb rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000123/saved_model.pb diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.index similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/variables/variables.index rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.index diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/assets/foo.txt rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000124/assets/foo.txt diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/saved_model.pb similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/saved_model.pb rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000124/saved_model.pb diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.index similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/variables/variables.index rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.index diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c79ebe01c240863890d2048ebee5da046c93a90a GIT binary patch literal 9337 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=6.2.2 \ No newline at end of file diff --git a/test/resources/mme2/half_plus_three/model/code/inference.py b/test/resources/mme2/half_plus_three/model/code/inference.py new file mode 100644 index 00000000..1809ce93 --- /dev/null +++ b/test/resources/mme2/half_plus_three/model/code/inference.py @@ -0,0 +1,58 @@ +# Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +import json +from collections import namedtuple + +import PIL + +Context = namedtuple('Context', + 'model_name, model_version, method, rest_uri, grpc_uri, ' + 'custom_attributes, request_content_type, accept_header') + + +def input_handler(data, context): + """ Pre-process request input before it is sent to TensorFlow Serving REST API + + Args: + data (obj): the request data, in format of dict or string + context (Context): an object containing request and configuration details + + Returns: + (dict): a JSON-serializable dict that contains request body and headers + """ + if context.request_content_type == 'application/json': + # pass through json (assumes it's correctly formed) + d = data.read().decode('utf-8') + return d if len(d) else '' + + raise ValueError('{{"error": "unsupported content type {}"}}'.format( + context.request_content_type or "unknown")) + + +def output_handler(data, context): + """Post-process TensorFlow Serving output before it is returned to the client. + + Args: + data (obj): the TensorFlow serving response + context (Context): an object containing request and configuration details + + Returns: + (bytes, string): data to return to client, response content type + """ + if data.status_code != 200: + raise ValueError(data.content.decode('utf-8')) + + response_content_type = context.accept_header + prediction = data.content + return prediction, response_content_type diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt new file mode 100644 index 00000000..f9ff0366 --- /dev/null +++ b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents \ No newline at end of file diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt new file mode 100644 index 00000000..56c3e54a --- /dev/null +++ b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/code/inference.py b/test/resources/mme2/half_plus_two/model/code/inference.py new file mode 100644 index 00000000..95b979da --- /dev/null +++ b/test/resources/mme2/half_plus_two/model/code/inference.py @@ -0,0 +1,59 @@ +# Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +import json +from collections import namedtuple + +import PIL + +Context = namedtuple('Context', + 'model_name, model_version, method, rest_uri, grpc_uri, ' + 'custom_attributes, request_content_type, accept_header') + + +def input_handler(data, context): + """ Pre-process request input before it is sent to TensorFlow Serving REST API + + Args: + data (obj): the request data, in format of dict or string + context (Context): an object containing request and configuration details + + Returns: + (dict): a JSON-serializable dict that contains request body and headers + """ + if context.request_content_type == 'text/csv': + # very simple csv handler + return json.dumps({ + 'instances': [float(x) for x in data.read().decode('utf-8').split(',')] + }) + + raise ValueError('{{"error": "unsupported content type {}"}}'.format( + context.request_content_type or "unknown")) + + +def output_handler(data, context): + """Post-process TensorFlow Serving output before it is returned to the client. + + Args: + data (obj): the TensorFlow serving response + context (Context): an object containing request and configuration details + + Returns: + (bytes, string): data to return to client, response content type + """ + if data.status_code != 200: + raise ValueError(data.content.decode('utf-8')) + + response_content_type = context.accept_header + prediction = data.content + return prediction, response_content_type diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c79ebe01c240863890d2048ebee5da046c93a90a GIT binary patch literal 9337 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=6.2.2 \ No newline at end of file diff --git a/test/resources/mme3/half_plus_three/model/code/inference.py b/test/resources/mme3/half_plus_three/model/code/inference.py new file mode 100644 index 00000000..fd12f017 --- /dev/null +++ b/test/resources/mme3/half_plus_three/model/code/inference.py @@ -0,0 +1,69 @@ +# Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + + +import json +from collections import namedtuple + +import requests + +import dummy_module # for testing requirements.txt install and pythonpath + +Context = namedtuple('Context', + 'model_name, model_version, method, rest_uri, grpc_uri, ' + 'custom_attributes, request_content_type, accept_header') + + +def handler(data, context): + """Handle request. + + Args: + data (obj): the request data + context (Context): an object containing request and configuration details + + Returns: + (bytes, string): data to return to client, (optional) response content type + """ + + # use the library in lib/ + print(dummy_module.__version__) + + # ensure the requirements.txt wasn't installed + try: + import PIL + raise Exception('pillow should not be installed') + except ImportError: + pass + + processed_input = _process_input(data, context) + response = requests.post(context.rest_uri, data=processed_input) + return _process_output(response, context) + + +def _process_input(data, context): + if context.request_content_type == 'application/json': + # pass through json (assumes it's correctly formed) + d = data.read().decode('utf-8') + return d if len(d) else '' + + raise ValueError('{{"error": "unsupported content type {}"}}'.format( + context.request_content_type or "unknown")) + + +def _process_output(data, context): + if data.status_code != 200: + raise ValueError(data.content.decode('utf-8')) + + response_content_type = context.accept_header + prediction = data.content + return prediction, response_content_type diff --git a/test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py b/test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py new file mode 100644 index 00000000..11d27f8c --- /dev/null +++ b/test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py @@ -0,0 +1 @@ +__version__ = '0.1' diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt new file mode 100644 index 00000000..f9ff0366 --- /dev/null +++ b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents \ No newline at end of file diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt new file mode 100644 index 00000000..56c3e54a --- /dev/null +++ b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c79ebe01c240863890d2048ebee5da046c93a90a GIT binary patch literal 9337 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5Fnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt new file mode 100644 index 00000000..56c3e54a --- /dev/null +++ b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c79ebe01c240863890d2048ebee5da046c93a90a GIT binary patch literal 9337 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5 Date: Mon, 15 Aug 2022 13:14:39 -0700 Subject: [PATCH 02/10] Feature: Support multiple inference.py files and universal inference.py file along with universal requirements.txt file --- README.md | 17 +- .../sagemaker/python_service.py | 38 +++- docker/build_artifacts/sagemaker/serve.py | 10 +- ...me.py => test_pre_post_processing_mme1.py} | 87 +++++---- .../local/test_pre_post_processing_mme2.py | 175 +++++++++++++++++ .../local/test_pre_post_processing_mme3.py | 176 +++++++++++++++++ .../local/test_pre_post_processing_mme4.py | 178 ++++++++++++++++++ .../code/inference.py | 0 .../code/requirements.txt | 0 .../half_plus_three/00000123/assets/foo.txt | 0 .../half_plus_three/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../half_plus_three/00000124/assets/foo.txt | 0 .../half_plus_three/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../half_plus_two/00000123/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000124/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes test/resources/mme2/code/inference.py | 29 +++ test/resources/mme2/code/requirements.txt | 1 + .../half_plus_three/model/code/inference.py | 58 ++++++ .../half_plus_three/00000123/assets/foo.txt | 1 + .../half_plus_three/00000123/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_three/00000124/assets/foo.txt | 1 + .../half_plus_three/00000124/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/model/code/inference.py | 59 ++++++ .../half_plus_two/00000123/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000124/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes test/resources/mme3/code/inference.py | 70 +++++++ .../mme3/code/lib/dummy_module/__init__.py | 1 + test/resources/mme3/code/requirements.txt | 1 + .../half_plus_three/model/code/inference.py | 69 +++++++ .../model/code/lib/dummy_module/__init__.py | 1 + .../half_plus_three/00000123/assets/foo.txt | 1 + .../half_plus_three/00000123/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_three/00000124/assets/foo.txt | 1 + .../half_plus_three/00000124/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000123/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000124/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_three/model/code/inference.py | 75 ++++++++ .../model/code/lib/dummy_module/__init__.py | 1 + .../half_plus_three/00000123/assets/foo.txt | 1 + .../half_plus_three/00000123/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_three/00000124/assets/foo.txt | 1 + .../half_plus_three/00000124/saved_model.pb | Bin 0 -> 8658 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000123/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes .../half_plus_two/00000124/saved_model.pb | Bin 0 -> 9337 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000124/variables/variables.index | Bin 0 -> 151 bytes 76 files changed, 1003 insertions(+), 49 deletions(-) rename test/integration/local/{test_pre_post_processing_mme.py => test_pre_post_processing_mme1.py} (55%) create mode 100644 test/integration/local/test_pre_post_processing_mme2.py create mode 100644 test/integration/local/test_pre_post_processing_mme3.py create mode 100644 test/integration/local/test_pre_post_processing_mme4.py rename test/resources/{mme_universal_script => mme1}/code/inference.py (100%) rename test/resources/{mme_universal_script => mme1}/code/requirements.txt (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000123/assets/foo.txt (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000123/saved_model.pb (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000123/variables/variables.index (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000124/assets/foo.txt (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000124/saved_model.pb (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/{mme_universal_script => mme1}/half_plus_three/model/half_plus_three/00000124/variables/variables.index (100%) create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000123/saved_model.pb create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.index create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000124/saved_model.pb create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.index create mode 100644 test/resources/mme2/code/inference.py create mode 100644 test/resources/mme2/code/requirements.txt create mode 100644 test/resources/mme2/half_plus_three/model/code/inference.py create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000123/saved_model.pb create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.index create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000124/saved_model.pb create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.index create mode 100644 test/resources/mme2/half_plus_two/model/code/inference.py create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000123/saved_model.pb create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.index create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000124/saved_model.pb create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.index create mode 100644 test/resources/mme3/code/inference.py create mode 100644 test/resources/mme3/code/lib/dummy_module/__init__.py create mode 100644 test/resources/mme3/code/requirements.txt create mode 100644 test/resources/mme3/half_plus_three/model/code/inference.py create mode 100644 test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000123/saved_model.pb create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.index create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000124/saved_model.pb create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.index create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000123/saved_model.pb create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.index create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000124/saved_model.pb create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.index create mode 100644 test/resources/mme4/half_plus_three/model/code/inference.py create mode 100644 test/resources/mme4/half_plus_three/model/code/lib/dummy_module/__init__.py create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000123/assets/foo.txt create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000123/saved_model.pb create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.index create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000124/saved_model.pb create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.index create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000123/saved_model.pb create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.index create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000124/saved_model.pb create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 create mode 100644 test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.index diff --git a/README.md b/README.md index 8447474f..e8042719 100644 --- a/README.md +++ b/README.md @@ -164,8 +164,6 @@ For example: ## Pre/Post-Processing -**NOTE: There is currently no support for pre-/post-processing with multi-model containers.** - SageMaker TensorFlow Serving Container supports the following Content-Types for requests: * `application/json` (default) @@ -672,7 +670,7 @@ Only 90% of the ports will be utilized and each loaded model will be allocated w For example, if the ``SAGEMAKER_SAFE_PORT_RANGE`` is between 9000 to 9999, the maximum number of models that can be loaded to the endpoint at the same time would be 499 ((9999 - 9000) * 0.9 / 2). ### Using Multi-Model Endpoint with Pre/Post-Processing -Multi-Model Endpoint can be used together with Pre/Post-Processing. Each model will need its own ``inference.py`` otherwise default handlers will be used. An example of the directory structure of Multi-Model Endpoint and Pre/Post-Processing would look like this: +Multi-Model Endpoint can be used together with Pre/Post-Processing. Each model can either have its own ``inference.py`` or use a universal ``inference.py``. If both model-specific and universal ``inference.py`` files are provided, then the model-specific ``inference.py`` file is used. If both files are absent, then the default handlers will be used. An example of the directory structure of Multi-Model Endpoint with a model-specific ``inference.py`` file would look like this: /opt/ml/models/model1/model |--[model_version_number] @@ -687,7 +685,20 @@ Multi-Model Endpoint can be used together with Pre/Post-Processing. Each model w |--lib |--external_module |--inference.py +Another example with of the directory structure of Multi-Model Endpoint with a universal ``inference.py`` file is as follows: + /opt/ml/models/model1/model + |--[model_version_number] + |--variables + |--saved_model.pb + /opt/ml/models/model2/model + |--[model_version_number] + |--assets + |--variables + |--saved_model.pb + code + |--requirements.txt + |--inference.py ## Contributing Please read [CONTRIBUTING.md](https://github.com/aws/sagemaker-tensorflow-serving-container/blob/master/CONTRIBUTING.md) diff --git a/docker/build_artifacts/sagemaker/python_service.py b/docker/build_artifacts/sagemaker/python_service.py index fd9954cc..23bdea9a 100644 --- a/docker/build_artifacts/sagemaker/python_service.py +++ b/docker/build_artifacts/sagemaker/python_service.py @@ -17,6 +17,7 @@ import os import subprocess import grpc +import sys import falcon import requests @@ -26,8 +27,8 @@ import tfs_utils SAGEMAKER_MULTI_MODEL_ENABLED = os.environ.get("SAGEMAKER_MULTI_MODEL", "false").lower() == "true" -MODEL_DIR = "models" if SAGEMAKER_MULTI_MODEL_ENABLED else "model" -INFERENCE_SCRIPT_PATH = f"/opt/ml/{MODEL_DIR}/code/inference.py" +MODEL_DIR = "" if SAGEMAKER_MULTI_MODEL_ENABLED else "model/" +INFERENCE_SCRIPT_PATH = f"/opt/ml/{MODEL_DIR}code/inference.py" SAGEMAKER_BATCHING_ENABLED = os.environ.get("SAGEMAKER_TFS_ENABLE_BATCHING", "false").lower() MODEL_CONFIG_FILE_PATH = "/sagemaker/model-config.cfg" @@ -77,6 +78,7 @@ def __init__(self): # between each grpc port and channel self._setup_channel(grpc_port) + self._default_handlers_enabled = False if os.path.exists(INFERENCE_SCRIPT_PATH): # Single-Model Mode & Multi-Model Mode both use one inference.py self._handler, self._input_handler, self._output_handler = self._import_handlers() @@ -85,6 +87,7 @@ def __init__(self): ) else: self._handlers = default_handler + self._default_handlers_enabled = True self._tfs_enable_batching = SAGEMAKER_BATCHING_ENABLED == "true" self._tfs_default_model_name = os.environ.get("TFS_DEFAULT_MODEL_NAME", "None") @@ -143,6 +146,7 @@ def _handle_load_model_post(self, res, data): # noqa: C901 # validate model files are in the specified base_path if self.validate_model_dir(base_path): try: + self._import_custom_modules(model_name) tfs_config = tfs_utils.create_tfs_config_individual_model(model_name, base_path) tfs_config_file = "/sagemaker/tfs-config/{}/model-config.cfg".format(model_name) log.info("tensorflow serving model config: \n%s\n", tfs_config) @@ -221,6 +225,17 @@ def _handle_load_model_post(self, res, data): # noqa: C901 } ) + def _import_custom_modules(self, model_name): + inference_script_path = "/opt/ml/models/{}/model/code/inference.py".format(model_name) + python_lib_path = "/opt/ml/models/{}/model/code/lib".format(model_name) + if os.path.exists(python_lib_path): + log.info("add Python code library path") + sys.path.append(python_lib_path) + if os.path.exists(inference_script_path): + handler, input_handler, output_handler = self._import_handlers(inference_script_path) + model_handlers = self._make_handler(handler, input_handler, output_handler) + self.model_handlers[model_name] = model_handlers + def _cleanup_config_file(self, config_file): if os.path.exists(config_file): os.remove(config_file) @@ -264,8 +279,20 @@ def _handle_invocation_post(self, req, res, model_name=None): try: res.status = falcon.HTTP_200 - - res.body, res.content_type = self._handlers(data, context) + handlers = self._handlers + if SAGEMAKER_MULTI_MODEL_ENABLED and model_name in self.model_handlers: + inference_script_path = "/opt/ml/models/{}/model/code/" \ + "inference.py".format(model_name) + log.info("Inference script found at path {}.".format(inference_script_path)) + log.info("Inference script exists, importing handlers.") + handlers = self.model_handlers[model_name] + elif not self._default_handlers_enabled: + log.info("Universal inference script found at path " + "{}.".format(INFERENCE_SCRIPT_PATH)) + log.info("Universal inference script exists, importing handlers.") + else: + log.info("Inference script does not exist, using default handlers.") + res.body, res.content_type = handlers(data, context) except Exception as e: # pylint: disable=broad-except log.exception("exception handling request: {}".format(e)) res.status = falcon.HTTP_500 @@ -276,8 +303,7 @@ def _setup_channel(self, grpc_port): log.info("Creating grpc channel for port: %s", grpc_port) self._channels[grpc_port] = grpc.insecure_channel("localhost:{}".format(grpc_port)) - def _import_handlers(self): - inference_script = INFERENCE_SCRIPT_PATH + def _import_handlers(self, inference_script=INFERENCE_SCRIPT_PATH): spec = importlib.util.spec_from_file_location("inference", inference_script) inference = importlib.util.module_from_spec(spec) spec.loader.exec_module(inference) diff --git a/docker/build_artifacts/sagemaker/serve.py b/docker/build_artifacts/sagemaker/serve.py index e5461346..ef885529 100644 --- a/docker/build_artifacts/sagemaker/serve.py +++ b/docker/build_artifacts/sagemaker/serve.py @@ -28,9 +28,8 @@ JS_INVOCATIONS = "js_content tensorflowServing.invocations" GUNICORN_PING = "proxy_pass http://gunicorn_upstream/ping" GUNICORN_INVOCATIONS = "proxy_pass http://gunicorn_upstream/invocations" -MULTI_MODEL = "s" if os.environ.get("SAGEMAKER_MULTI_MODEL", "False").lower() == "true" else "" -MODEL_DIR = f"model{MULTI_MODEL}" -CODE_DIR = "/opt/ml/{}/code".format(MODEL_DIR) +MODEL_DIR = "" if os.environ.get("SAGEMAKER_MULTI_MODEL", "False").lower() == "true" else "model" +CODE_DIR = f"/opt/ml/{MODEL_DIR}/code" PYTHON_LIB_PATH = os.path.join(CODE_DIR, "lib") REQUIREMENTS_PATH = os.path.join(CODE_DIR, "requirements.txt") INFERENCE_PATH = os.path.join(CODE_DIR, "inference.py") @@ -134,7 +133,8 @@ def __init__(self): os.environ["TFS_REST_PORTS"] = self._tfs_rest_concat_ports def _need_python_service(self): - if os.path.exists(INFERENCE_PATH): + if (os.path.exists(INFERENCE_PATH) or os.path.exists(REQUIREMENTS_PATH) + or os.path.exists(PYTHON_LIB_PATH)): self._enable_python_service = True if os.environ.get("SAGEMAKER_MULTI_MODEL_UNIVERSAL_BUCKET") and os.environ.get( "SAGEMAKER_MULTI_MODEL_UNIVERSAL_PREFIX" @@ -256,7 +256,7 @@ def _download_scripts(self, bucket, prefix): paginator = client.get_paginator("list_objects") for result in paginator.paginate(Bucket=bucket, Delimiter="/", Prefix=prefix): for file in result.get("Contents", []): - destination = os.path.join(CODE_DIR, file.get("Key")) + destination = os.path.join(CODE_DIR, file.get("Key").split("/")[-1]) if not os.path.exists(os.path.dirname(destination)): os.makedirs(os.path.dirname(destination)) resource.meta.client.download_file(bucket, file.get("Key"), destination) diff --git a/test/integration/local/test_pre_post_processing_mme.py b/test/integration/local/test_pre_post_processing_mme1.py similarity index 55% rename from test/integration/local/test_pre_post_processing_mme.py rename to test/integration/local/test_pre_post_processing_mme1.py index 5eb0fb6e..91ac2898 100644 --- a/test/integration/local/test_pre_post_processing_mme.py +++ b/test/integration/local/test_pre_post_processing_mme1.py @@ -11,9 +11,11 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +# In this test, only a universal inference.py file is provided. It's expected the handlers from the universal +# inference.py file should be used by both models. + import json import os -import shutil import subprocess import sys import time @@ -27,19 +29,19 @@ PING_URL = "http://localhost:8080/ping" INVOCATION_URL = "http://localhost:8080/models/{}/invoke" -MODEL_NAME = "half_plus_three" +MODEL_NAMES = ["half_plus_three","half_plus_two"] @pytest.fixture(scope="session", autouse=True) def volume(): try: - model_dir = os.path.abspath("test/resources/mme_universal_script") + model_dir = os.path.abspath("test/resources/mme1") subprocess.check_call( - "docker volume create --name model_volume_mme --opt type=none " + "docker volume create --name model_volume_mme1 --opt type=none " "--opt device={} --opt o=bind".format(model_dir).split()) yield model_dir finally: - subprocess.check_call("docker volume rm model_volume_mme".split()) + subprocess.check_call("docker volume rm model_volume_mme1".split()) @pytest.fixture(scope="module", autouse=True) @@ -47,7 +49,7 @@ def container(docker_base_name, tag, runtime_config): try: command = ( "docker run {}--name sagemaker-tensorflow-serving-test -p 8080:8080" - " --mount type=volume,source=model_volume_mme,target=/opt/ml/models,readonly" + " --mount type=volume,source=model_volume_mme1,target=/opt/ml,readonly" " -e SAGEMAKER_TFS_NGINX_LOGLEVEL=info" " -e SAGEMAKER_BIND_TO_PORT=8080" " -e SAGEMAKER_SAFE_PORT_RANGE=9000-9999" @@ -74,13 +76,14 @@ def container(docker_base_name, tag, runtime_config): @pytest.fixture -def model(): - model_data = { - "model_name": MODEL_NAME, - "url": "/opt/ml/models/half_plus_three/model/half_plus_three" - } - make_load_model_request(json.dumps(model_data)) - return MODEL_NAME +def models(): + for MODEL_NAME in MODEL_NAMES: + model_data = { + "model_name": MODEL_NAME, + "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + } + make_load_model_request(json.dumps(model_data)) + return MODEL_NAMES @pytest.mark.skip_gpu @@ -90,20 +93,25 @@ def test_ping_service(): @pytest.mark.skip_gpu -def test_predict_json(model): +def test_predict_json(models): headers = make_headers() data = "{\"instances\": [1.0, 2.0, 5.0]}" - response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() - assert response == {"predictions": [3.5, 4.0, 5.5]} + responses = [] + for model in models: + response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} @pytest.mark.skip_gpu def test_zero_content(): headers = make_headers() x = "" - response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) - assert 500 == response.status_code - assert "document is empty" in response.text + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) + assert 500 == response.status_code + assert "document is empty" in response.text @pytest.mark.skip_gpu @@ -113,34 +121,43 @@ def test_large_input(): with open(data_file, "r") as file: x = file.read() headers = make_headers(content_type="text/csv") - response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() - predictions = response["predictions"] - assert len(predictions) == 753936 + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() + predictions = response["predictions"] + assert len(predictions) == 753936 @pytest.mark.skip_gpu def test_csv_input(): headers = make_headers(content_type="text/csv") data = "1.0,2.0,5.0" - response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() - assert response == {"predictions": [3.5, 4.0, 5.5]} - + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} @pytest.mark.skip_gpu def test_specific_versions(): - for version in ("123", "124"): - headers = make_headers(content_type="text/csv", version=version) - data = "1.0,2.0,5.0" - response = requests.post( - INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers - ).json() - assert response == {"predictions": [3.5, 4.0, 5.5]} + for MODEL_NAME in MODEL_NAMES: + for version in ("123", "124"): + headers = make_headers(content_type="text/csv", version=version) + data = "1.0,2.0,5.0" + response = requests.post( + INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers + ).json() + if MODEL_NAME == "half_plus_three": + assert response == {"predictions": [3.5, 4.0, 5.5]} + else: + assert response == {"predictions": [2.5, 3.0, 4.5]} @pytest.mark.skip_gpu def test_unsupported_content_type(): headers = make_headers("unsupported-type", "predict") data = "aW1hZ2UgYnl0ZXM=" - response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) - assert 500 == response.status_code - assert "unsupported content type" in response.text + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) + assert 500 == response.status_code + assert "unsupported content type" in response.text diff --git a/test/integration/local/test_pre_post_processing_mme2.py b/test/integration/local/test_pre_post_processing_mme2.py new file mode 100644 index 00000000..c09ff2ee --- /dev/null +++ b/test/integration/local/test_pre_post_processing_mme2.py @@ -0,0 +1,175 @@ +# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +# The model-specific inference.py files for both models and the universal inference.py file are provided. It is +# expected that the handlers from the model-specific inference.py files should be used and the handlers from the +# universal inference.py file should be ignored. + +import json +import os +import subprocess +import sys +import time + +import pytest + +import requests + +from multi_model_endpoint_test_utils import make_load_model_request, make_headers + + +PING_URL = "http://localhost:8080/ping" +INVOCATION_URL = "http://localhost:8080/models/{}/invoke" +MODEL_NAMES = ["half_plus_three","half_plus_two"] + + +@pytest.fixture(scope="session", autouse=True) +def volume(): + try: + model_dir = os.path.abspath("test/resources/mme2") + subprocess.check_call( + "docker volume create --name model_volume_mme2 --opt type=none " + "--opt device={} --opt o=bind".format(model_dir).split()) + yield model_dir + finally: + subprocess.check_call("docker volume rm model_volume_mme2".split()) + + +@pytest.fixture(scope="module", autouse=True) +def container(docker_base_name, tag, runtime_config): + try: + command = ( + "docker run {}--name sagemaker-tensorflow-serving-test -p 8080:8080" + " --mount type=volume,source=model_volume_mme2,target=/opt/ml,readonly" + " -e SAGEMAKER_TFS_NGINX_LOGLEVEL=info" + " -e SAGEMAKER_BIND_TO_PORT=8080" + " -e SAGEMAKER_SAFE_PORT_RANGE=9000-9999" + " -e SAGEMAKER_MULTI_MODEL=True" + " {}:{} serve" + ).format(runtime_config, docker_base_name, tag) + + proc = subprocess.Popen(command.split(), stdout=sys.stdout, stderr=subprocess.STDOUT) + + attempts = 0 + while attempts < 40: + time.sleep(3) + try: + res_code = requests.get("http://localhost:8080/ping").status_code + if res_code == 200: + break + except: + attempts += 1 + pass + + yield proc.pid + finally: + subprocess.check_call("docker rm -f sagemaker-tensorflow-serving-test".split()) + + +@pytest.fixture +def models(): + for MODEL_NAME in MODEL_NAMES: + model_data = { + "model_name": MODEL_NAME, + "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + } + make_load_model_request(json.dumps(model_data)) + return MODEL_NAMES + + +@pytest.mark.skip_gpu +def test_ping_service(): + response = requests.get(PING_URL) + assert 200 == response.status_code + + +@pytest.mark.skip_gpu +def test_predict_json(models): + headers = make_headers() + data = "{\"instances\": [1.0, 2.0, 5.0]}" + responses = [] + for model in models: + response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + error = responses[1]["error"] + assert "unsupported content type application/json" in error + + +@pytest.mark.skip_gpu +def test_zero_content(): + headers = make_headers() + x = "" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) + responses.append(response) + print(MODEL_NAME,response) + assert 500 == responses[0].status_code + assert "document is empty" in responses[0].text + assert 500 == responses[1].status_code + assert "unsupported content type application/json" in responses[1].text + + +@pytest.mark.skip_gpu +def test_large_input(): + data_file = "test/resources/inputs/test-large.csv" + + with open(data_file, "r") as file: + x = file.read() + headers = make_headers(content_type="text/csv") + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() + responses.append(response) + error = responses[0]["error"] + assert "unsupported content type text/csv" in error + predictions = responses[1]["predictions"] + assert len(predictions) == 753936 + + +@pytest.mark.skip_gpu +def test_csv_input(): + headers = make_headers(content_type="text/csv") + data = "1.0,2.0,5.0" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() + responses.append(response) + error = responses[0]["error"] + assert "unsupported content type text/csv" in error + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} + +@pytest.mark.skip_gpu +def test_specific_versions(): + for MODEL_NAME in MODEL_NAMES: + for version in ("123", "124"): + headers = make_headers(content_type="text/csv", version=version) + data = "1.0,2.0,5.0" + response = requests.post( + INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers + ).json() + if MODEL_NAME == "half_plus_three": + error = response["error"] + assert "unsupported content type text/csv" in error + else: + assert response == {"predictions": [2.5, 3.0, 4.5]} + +@pytest.mark.skip_gpu +def test_unsupported_content_type(): + headers = make_headers("unsupported-type", "predict") + data = "aW1hZ2UgYnl0ZXM=" + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) + assert 500 == response.status_code + assert "unsupported content type" in response.text diff --git a/test/integration/local/test_pre_post_processing_mme3.py b/test/integration/local/test_pre_post_processing_mme3.py new file mode 100644 index 00000000..b0250fb8 --- /dev/null +++ b/test/integration/local/test_pre_post_processing_mme3.py @@ -0,0 +1,176 @@ +# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +# A model-specific inference.py file for the model half_plus_three and a universal inference.py file are provided. A +# specific inference.py file for the model half_plus_two is not provided. It is expected that the handlers from the +# model-specific inference.py file should be used for the model half_plus_three and the handlers from the universal +# inference.py file should be used for the model half_plus_two. +import json +import os +import subprocess +import sys +import time + +import pytest + +import requests + +from multi_model_endpoint_test_utils import make_load_model_request, make_headers + + +PING_URL = "http://localhost:8080/ping" +INVOCATION_URL = "http://localhost:8080/models/{}/invoke" +MODEL_NAMES = ["half_plus_three","half_plus_two"] + + +@pytest.fixture(scope="session", autouse=True) +def volume(): + try: + model_dir = os.path.abspath("test/resources/mme3") + subprocess.check_call( + "docker volume create --name model_volume_mme3 --opt type=none " + "--opt device={} --opt o=bind".format(model_dir).split()) + yield model_dir + finally: + subprocess.check_call("docker volume rm model_volume_mme3".split()) + + +@pytest.fixture(scope="module", autouse=True) +def container(docker_base_name, tag, runtime_config): + try: + command = ( + "docker run {}--name sagemaker-tensorflow-serving-test -p 8080:8080" + " --mount type=volume,source=model_volume_mme3,target=/opt/ml,readonly" + " -e SAGEMAKER_TFS_NGINX_LOGLEVEL=info" + " -e SAGEMAKER_BIND_TO_PORT=8080" + " -e SAGEMAKER_SAFE_PORT_RANGE=9000-9999" + " -e SAGEMAKER_MULTI_MODEL=True" + " {}:{} serve" + ).format(runtime_config, docker_base_name, tag) + + proc = subprocess.Popen(command.split(), stdout=sys.stdout, stderr=subprocess.STDOUT) + + attempts = 0 + while attempts < 40: + time.sleep(3) + try: + res_code = requests.get("http://localhost:8080/ping").status_code + if res_code == 200: + break + except: + attempts += 1 + pass + + yield proc.pid + finally: + subprocess.check_call("docker rm -f sagemaker-tensorflow-serving-test".split()) + + +@pytest.fixture +def models(): + for MODEL_NAME in MODEL_NAMES: + model_data = { + "model_name": MODEL_NAME, + "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + } + make_load_model_request(json.dumps(model_data)) + return MODEL_NAMES + + +@pytest.mark.skip_gpu +def test_ping_service(): + response = requests.get(PING_URL) + assert 200 == response.status_code + + +@pytest.mark.skip_gpu +def test_predict_json(models): + headers = make_headers() + data = "{\"instances\": [1.0, 2.0, 5.0]}" + responses = [] + for model in models: + response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + error = responses[1]["error"] + assert "unsupported content type application/json" in error + + +@pytest.mark.skip_gpu +def test_zero_content(): + headers = make_headers() + x = "" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) + responses.append(response) + print(MODEL_NAME,response) + assert 500 == responses[0].status_code + assert "document is empty" in responses[0].text + assert 500 == responses[1].status_code + assert "unsupported content type application/json" in responses[1].text + + +@pytest.mark.skip_gpu +def test_large_input(): + data_file = "test/resources/inputs/test-large.csv" + + with open(data_file, "r") as file: + x = file.read() + headers = make_headers(content_type="text/csv") + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() + responses.append(response) + error = responses[0]["error"] + assert "unsupported content type text/csv" in error + predictions = responses[1]["predictions"] + assert len(predictions) == 753936 + + +@pytest.mark.skip_gpu +def test_csv_input(): + headers = make_headers(content_type="text/csv") + data = "1.0,2.0,5.0" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() + responses.append(response) + error = responses[0]["error"] + assert "unsupported content type text/csv" in error + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} + +@pytest.mark.skip_gpu +def test_specific_versions(): + for MODEL_NAME in MODEL_NAMES: + for version in ("123", "124"): + headers = make_headers(content_type="text/csv", version=version) + data = "1.0,2.0,5.0" + response = requests.post( + INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers + ).json() + if MODEL_NAME == "half_plus_three": + error = response["error"] + assert "unsupported content type text/csv" in error + else: + assert response == {"predictions": [2.5, 3.0, 4.5]} + + +@pytest.mark.skip_gpu +def test_unsupported_content_type(): + headers = make_headers("unsupported-type", "predict") + data = "aW1hZ2UgYnl0ZXM=" + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) + assert 500 == response.status_code + assert "unsupported content type" in response.text diff --git a/test/integration/local/test_pre_post_processing_mme4.py b/test/integration/local/test_pre_post_processing_mme4.py new file mode 100644 index 00000000..fb4f0306 --- /dev/null +++ b/test/integration/local/test_pre_post_processing_mme4.py @@ -0,0 +1,178 @@ +# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +# Only a model-specific inference.py file for the model half_plus_three is provided. Neither a specific inference.py +# file for the model half_plus_two nor a universal inference.py file is provided. It is expected that the handlers +# from the model-specific inference.py file should be used for the model half_plus_three and the default handlers +# should be used for the model half_plus_two. +import json +import os +import subprocess +import sys +import time + +import pytest + +import requests + +from multi_model_endpoint_test_utils import make_load_model_request, make_headers + + +PING_URL = "http://localhost:8080/ping" +INVOCATION_URL = "http://localhost:8080/models/{}/invoke" +MODEL_NAMES = ["half_plus_three","half_plus_two"] + + +@pytest.fixture(scope="session", autouse=True) +def volume(): + try: + model_dir = os.path.abspath("test/resources/mme4") + subprocess.check_call( + "docker volume create --name model_volume_mme4 --opt type=none " + "--opt device={} --opt o=bind".format(model_dir).split()) + yield model_dir + finally: + subprocess.check_call("docker volume rm model_volume_mme4".split()) + + +@pytest.fixture(scope="module", autouse=True) +def container(docker_base_name, tag, runtime_config): + try: + command = ( + "docker run {}--name sagemaker-tensorflow-serving-test -p 8080:8080" + " --mount type=volume,source=model_volume_mme4,target=/opt/ml,readonly" + " -e SAGEMAKER_TFS_NGINX_LOGLEVEL=info" + " -e SAGEMAKER_BIND_TO_PORT=8080" + " -e SAGEMAKER_SAFE_PORT_RANGE=9000-9999" + " -e SAGEMAKER_MULTI_MODEL=True" + " {}:{} serve" + ).format(runtime_config, docker_base_name, tag) + + proc = subprocess.Popen(command.split(), stdout=sys.stdout, stderr=subprocess.STDOUT) + + attempts = 0 + while attempts < 40: + time.sleep(3) + try: + res_code = requests.get("http://localhost:8080/ping").status_code + if res_code == 200: + break + except: + attempts += 1 + pass + + yield proc.pid + finally: + subprocess.check_call("docker rm -f sagemaker-tensorflow-serving-test".split()) + + +@pytest.fixture +def models(): + for MODEL_NAME in MODEL_NAMES: + model_data = { + "model_name": MODEL_NAME, + "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + } + make_load_model_request(json.dumps(model_data)) + return MODEL_NAMES + + +@pytest.mark.skip_gpu +def test_ping_service(): + response = requests.get(PING_URL) + assert 200 == response.status_code + + +@pytest.mark.skip_gpu +def test_predict_json(models): + headers = make_headers() + data = "{\"instances\": [1.0, 2.0, 5.0]}" + responses = [] + for model in models: + response = requests.post(INVOCATION_URL.format(model), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + assert responses[1] == {"predictions": [2.5, 3.0, 4.5]} + + +@pytest.mark.skip_gpu +def test_zero_content(): + headers = make_headers() + x = "" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers) + responses.append(response) + print(MODEL_NAME,response) + assert 500 == responses[0].status_code + assert "document is empty" in responses[0].text + assert 200 == responses[1].status_code + assert "document is empty" in responses[1].text + + +@pytest.mark.skip_gpu +def test_large_input(): + data_file = "test/resources/inputs/test-large.csv" + + with open(data_file, "r") as file: + x = file.read() + headers = make_headers(content_type="text/csv") + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=x, headers=headers).json() + responses.append(response) + predictions = responses[0]["predictions"] + assert len(predictions) == 753936 + error = responses[1]["error"] + assert "document root must not be followed by other values" in error + + +@pytest.mark.skip_gpu +def test_csv_input(): + headers = make_headers(content_type="text/csv") + data = "1.0,2.0,5.0" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers).json() + responses.append(response) + assert responses[0] == {"predictions": [3.5, 4.0, 5.5]} + error = responses[1]["error"] + assert "document root must not be followed by other values" in error + +@pytest.mark.skip_gpu +def test_specific_versions(): + for MODEL_NAME in MODEL_NAMES: + for version in ("123", "124"): + headers = make_headers(content_type="text/csv", version=version) + data = "1.0,2.0,5.0" + response = requests.post( + INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers + ).json() + if MODEL_NAME == 'half_plus_three': + assert response == {"predictions": [3.5, 4.0, 5.5]} + else: + error = response["error"] + assert "document root must not be followed by other values" in error + +@pytest.mark.skip_gpu +def test_unsupported_content_type(): + headers = make_headers("unsupported-type", "predict") + data = "aW1hZ2UgYnl0ZXM=" + responses = [] + for MODEL_NAME in MODEL_NAMES: + response = requests.post(INVOCATION_URL.format(MODEL_NAME), data=data, headers=headers) + responses.append(response) + assert 500 == responses[0].status_code + assert "unsupported content type" in responses[0].text + assert 200 == responses[1].status_code + assert "Invalid value" in responses[1].text diff --git a/test/resources/mme_universal_script/code/inference.py b/test/resources/mme1/code/inference.py similarity index 100% rename from test/resources/mme_universal_script/code/inference.py rename to test/resources/mme1/code/inference.py diff --git a/test/resources/mme_universal_script/code/requirements.txt b/test/resources/mme1/code/requirements.txt similarity index 100% rename from test/resources/mme_universal_script/code/requirements.txt rename to test/resources/mme1/code/requirements.txt diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/assets/foo.txt rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000123/assets/foo.txt diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/saved_model.pb similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/saved_model.pb rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000123/saved_model.pb diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.index similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000123/variables/variables.index rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.index diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/assets/foo.txt rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000124/assets/foo.txt diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/saved_model.pb similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/saved_model.pb rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000124/saved_model.pb diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.index similarity index 100% rename from test/resources/mme_universal_script/half_plus_three/model/half_plus_three/00000124/variables/variables.index rename to test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.index diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c79ebe01c240863890d2048ebee5da046c93a90a GIT binary patch literal 9337 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=6.2.2 \ No newline at end of file diff --git a/test/resources/mme2/half_plus_three/model/code/inference.py b/test/resources/mme2/half_plus_three/model/code/inference.py new file mode 100644 index 00000000..1809ce93 --- /dev/null +++ b/test/resources/mme2/half_plus_three/model/code/inference.py @@ -0,0 +1,58 @@ +# Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +import json +from collections import namedtuple + +import PIL + +Context = namedtuple('Context', + 'model_name, model_version, method, rest_uri, grpc_uri, ' + 'custom_attributes, request_content_type, accept_header') + + +def input_handler(data, context): + """ Pre-process request input before it is sent to TensorFlow Serving REST API + + Args: + data (obj): the request data, in format of dict or string + context (Context): an object containing request and configuration details + + Returns: + (dict): a JSON-serializable dict that contains request body and headers + """ + if context.request_content_type == 'application/json': + # pass through json (assumes it's correctly formed) + d = data.read().decode('utf-8') + return d if len(d) else '' + + raise ValueError('{{"error": "unsupported content type {}"}}'.format( + context.request_content_type or "unknown")) + + +def output_handler(data, context): + """Post-process TensorFlow Serving output before it is returned to the client. + + Args: + data (obj): the TensorFlow serving response + context (Context): an object containing request and configuration details + + Returns: + (bytes, string): data to return to client, response content type + """ + if data.status_code != 200: + raise ValueError(data.content.decode('utf-8')) + + response_content_type = context.accept_header + prediction = data.content + return prediction, response_content_type diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt new file mode 100644 index 00000000..f9ff0366 --- /dev/null +++ b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents \ No newline at end of file diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt new file mode 100644 index 00000000..56c3e54a --- /dev/null +++ b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/code/inference.py b/test/resources/mme2/half_plus_two/model/code/inference.py new file mode 100644 index 00000000..95b979da --- /dev/null +++ b/test/resources/mme2/half_plus_two/model/code/inference.py @@ -0,0 +1,59 @@ +# Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +import json +from collections import namedtuple + +import PIL + +Context = namedtuple('Context', + 'model_name, model_version, method, rest_uri, grpc_uri, ' + 'custom_attributes, request_content_type, accept_header') + + +def input_handler(data, context): + """ Pre-process request input before it is sent to TensorFlow Serving REST API + + Args: + data (obj): the request data, in format of dict or string + context (Context): an object containing request and configuration details + + Returns: + (dict): a JSON-serializable dict that contains request body and headers + """ + if context.request_content_type == 'text/csv': + # very simple csv handler + return json.dumps({ + 'instances': [float(x) for x in data.read().decode('utf-8').split(',')] + }) + + raise ValueError('{{"error": "unsupported content type {}"}}'.format( + context.request_content_type or "unknown")) + + +def output_handler(data, context): + """Post-process TensorFlow Serving output before it is returned to the client. + + Args: + data (obj): the TensorFlow serving response + context (Context): an object containing request and configuration details + + Returns: + (bytes, string): data to return to client, response content type + """ + if data.status_code != 200: + raise ValueError(data.content.decode('utf-8')) + + response_content_type = context.accept_header + prediction = data.content + return prediction, response_content_type diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c79ebe01c240863890d2048ebee5da046c93a90a GIT binary patch literal 9337 zcmd5?-H+Q?70=Cg&ZL>loqnWu+U*k2cJN9~CPSAtD$q^EYC-ByXeq3a#&T>=YfUE3 z#-4Uk9@qySKtgB*LLeaoJRFNP?*|B_`#=yP=L}aV{~eBI(Xxr`jb;%kKVUy5zRJ(1}=3h!?$(sr7^K- zap<}umft1qE3k3u+4{&ekDc+0`HSBZ0{5Ww$Q^q=+k~>D-!55P%Jyc!oR)oi?77qS z1(0u~7H|iu-?r?r@Axw=s53^{xS$&mA=G*ri-nI$F~W zTfz^Y;pb&29=P9~z+)&rG0bDyfU&9=oJVV!ER3ipH7aiFYjD z%E3SLP=8`fJ^Nc{#>r%4BVF+9se>+iV_T?h4N7Cc{pBO`%l|A$F9SL;H6ZtR}XHv|2@W{ z*CL=2pI(N#8rMKgL26>XMZn zhQvi^3O>3qwsdbK99dyoP?77<-y&zdb_;^5q}95Fr^X1%PmNb^$&Ied?IYNH`qG$M zw)LSivbiR-4%MOIiEA11sMOSI6?is`PfvK^np$3~z;NMF@KLJ*2LMm~DVDD9V9lTx zpe$+)&kRgRG@PtkSR0c0cm-;njfrHSiD}sr6j+|-zyo-0VD1e^XbX%CQE_E$!>ZeE zBtt=|dst0traSfxXKW|Pwy$E|q5`%h+!p7E#&4G}-Cx;SY46VcJKbL8bbLH^Uytb@ z_rZisqvMPnAFF{b@`=it+`iDU>{saQ{-Y;9=y$b^umI<~M7sgK7cBrIjxw><-Q3%5QE0lR%vg>wL&9tW`Zu|L|5XxmDHbG`nLqCMkm48492uU6X;YiEr!$_FdWur5-4U0y5 z7>cz-ibedgh@(G;EBSMws~)aoZ0^tD|Hhxgls|_|Rd|UdRhW|H&*7T>9H#s^Tp~r< zpTo>xL4TSn`E#W#S>*JG54k_hW&T`=b~*#KrFkv#(@go(WU9idB^M>2xrW2Ej-?E zQPQ`g~3L(AO-9rWcf9Li;K9@5SOt${6p|@Ydtpu0EjYQ)7u%LG{I42@G zD?@1Lgxa7|tIJ)|Kcmg=a_&12j1AIqK`1ft-k{RV~874_fkns8G{s>Aas=i0hkvLRPTUB)U81l286j`!h!A__Oy*}v? zU|Pi-x)V>RPW-07r*d0W{`oHZu{06t5_c*}@I{c$&-PSftzeW@Qnk)OnCtim?3OH5{B>~oy7xOP+54MzVA~}PvRIg)m5ayo*9GZvoM}jk>>Jxnrz6AC8 zvWU+{Y$ZIw4j6VL67VQ~_Nin6@+4T``&8+~#hxJij6h3}oOcTlw_{t$)e)WEL|NhYG+QYkh_R-hwcaM&Y&cvAdD~SiE zu&GEvWBm&j)0$<9%k$`f@;Z+Ie%{64_%LJlhVKPz=Z%z5=h)_7$od@jgaCo@&A&i% z9DN-FlbR&^I2`g#t@Ahhb(rPgmk9M1aieM*iK*sgOQZ}I&yAwwY?eI`aRts19kWin zA$Pv!l_mJGpj``1y*=2%807G}Fd)W&3R~q)u~NQR`CnfHD65OyG(Th&SA( z?ueH=dyH_`oW=IB#p2ZuW2&f5za2G@uEP$!DjG;~c{0+oq9feqD)4s#?};zdvyIMz z!3Gsmg)ECok<-em;%7UNXb_AZIARPi0!|QQH6c97q(#%>(gougwvKM`%BD(uDLu8p z#t;00;EaJsTr^3V_u~?EQd%Z0G;6JDvy8GC*$Cdiju0j4$*+?0OH+CE%=-!4PcPR}?Dl#HG<{2>fwDH$S;sNX$g&7^(P_&P%Kt2eyYYLKeZ_2$x< zDd|!WeUa_H$adckfeHgnrc{V9%$ zIC#g|jvP99^f!clMsR{&Fpy+4Az^sMhZ6m6Z%dg7^}F}P`XOH*okZ{|T(3+V!u2L! zA0Ag2UWMzGjy7N4{tJQH|GSL0VVnEI(goz#PtdlyJHe4D7LWLeLwki?dp;s^j<7GP z`>sBtCcG2Q4(Ualu|`ecez#d+Sb6A|q3oG1I+HRe%5dB9kznv>_A{0(7vVK*PVE<{g%@bvqt>~q z--3!9Cwi1~&JvKZ1G>iTBL~N literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=6.2.2 \ No newline at end of file diff --git a/test/resources/mme3/half_plus_three/model/code/inference.py b/test/resources/mme3/half_plus_three/model/code/inference.py new file mode 100644 index 00000000..fd12f017 --- /dev/null +++ b/test/resources/mme3/half_plus_three/model/code/inference.py @@ -0,0 +1,69 @@ +# Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + + +import json +from collections import namedtuple + +import requests + +import dummy_module # for testing requirements.txt install and pythonpath + +Context = namedtuple('Context', + 'model_name, model_version, method, rest_uri, grpc_uri, ' + 'custom_attributes, request_content_type, accept_header') + + +def handler(data, context): + """Handle request. + + Args: + data (obj): the request data + context (Context): an object containing request and configuration details + + Returns: + (bytes, string): data to return to client, (optional) response content type + """ + + # use the library in lib/ + print(dummy_module.__version__) + + # ensure the requirements.txt wasn't installed + try: + import PIL + raise Exception('pillow should not be installed') + except ImportError: + pass + + processed_input = _process_input(data, context) + response = requests.post(context.rest_uri, data=processed_input) + return _process_output(response, context) + + +def _process_input(data, context): + if context.request_content_type == 'application/json': + # pass through json (assumes it's correctly formed) + d = data.read().decode('utf-8') + return d if len(d) else '' + + raise ValueError('{{"error": "unsupported content type {}"}}'.format( + context.request_content_type or "unknown")) + + +def _process_output(data, context): + if data.status_code != 200: + raise ValueError(data.content.decode('utf-8')) + + response_content_type = context.accept_header + prediction = data.content + return prediction, response_content_type diff --git a/test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py b/test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py new file mode 100644 index 00000000..11d27f8c --- /dev/null +++ b/test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py @@ -0,0 +1 @@ +__version__ = '0.1' diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt new file mode 100644 index 00000000..f9ff0366 --- /dev/null +++ b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents \ No newline at end of file diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt new file mode 100644 index 00000000..56c3e54a --- /dev/null +++ b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c79ebe01c240863890d2048ebee5da046c93a90a GIT binary patch literal 9337 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5Fnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt new file mode 100644 index 00000000..56c3e54a --- /dev/null +++ b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..71ac858241500dae98fba4ddb4c4e3abe4581ca2 GIT binary patch literal 8658 zcmcgx-*Ven8TYYc%l_;n%}LrirwzN90lMxqcHB0!-pFnhtpas%A#V{pqG@E}|xj(B$!mOIsTl3ywn3zag}-~>vK zeBT}nX%z|{-^cg=KnMjW9vjXP7i93pJqkugfj(YuRK_Hc`U<{kTSmZj|G*e=y3}`F zhvjdO##N{u`CNBg^R+!3Ocwr52;76>V|VBWY!yn1exqm!Asee9b6N`c(09GYGN=`$ z1Z+e3Ba06MJ2(}B+C!902wEKzLZv4XLLcZe?hW`SoyP~0HCVN{!%UuJ$Xy( zu%ez@eBU^70>4vwDIc(FuoBX;hn8(3{mPge+k)kAQK{Ieg|`BGpRw_>+)Rm2uRu+4 z48IKdH7>zeSY;P9MI>eT;Jc7uL&35A;D%uN-VM^#px7ypiq?1sLYi4GY(*j{>1b8b zkvB*P9zpfFW0?E^w+Q#9w{~(THz*X9%cvig@8-aP%Fl88xgPFU+}nH|h{xCDm#Zu%YzAIKCh&dM;KU!s?3y!?U>c z)ONVgf!3hhH+*@mb|b3eS@nY0sKcW}5l=kJuNN4;xF3F0*I*CeMc`pX`7ydOU51hj z0bGdg3u}R(7`A+wEJP+39Q@N7p;IcG{g= zgPps#ca3{@Zegs!Q1{;syo6PwWe@EDU09b+KvfWJR-+J^Z_P$o3jT*~Eg zKWtus6+MjPC>J^#T>`P=I1q!zERZCIl;ztLUu~|&bw$%P*OEGlM_FwCM4)W6!fX>} z9Yze6R;jr$l~FL4;M0V(73%HehE|fX%=NjUQHV zVG=4ssk=n;Wzziq6xx?zy}L%M<^M&0h#$UK8<%&u6`C|v+vPzds;H1FLZL%Qb9quD ziqiO(*ek`tf3}q-8~d!%!3U}r5DftfGYvzK#+l?CgvcostsPUeRD`?$p(l_(>Ch~n zBWLxw_o0Y7={q!`8j_xfl;K(EuSO6Z!|d|yIM6|SwUs{0~);7jcMQ}u9Ke3sz*by_fAt4en)9=bTY$=p_dBv6+mCv7Dv{M%WIO4&XXsqOG#e{C3N+WnteVwg{R)`UB-!w{Fy(vJ8L4M? zlApoGEb25pUtno-vN=+PFHek+soX)dS>)iP6(7pXP)%!Ij|{ioTf@yFYMnxl7(LSO z5wnT&(^QEY6+{J`&RkcDDo(OsiVb^aa@&l!UFxljx#fEJKbO_-v5^-}^+K|u;Z%st zG<3B4ruAoY3 zmc2g+d={E)T0A;qs!sw~Y}U9C)uKT$s` z!f?1Id5>qMi~TT_6=ctWemKW12pqsWDK=+v!o&nlxjdQcfCRoEI5ij69BV`;gWxzC zY@Xt5k+`BWQd40Xc1GDH`{yJK3aKIm-8dy`Mq%>x&FluSl{AjNb5X$ia{>PpzCFe0 zZ9)E5f&=^nP#qX z3BtUub}3s?*(BPtsrwH0AZqJIlnloS>8z_SqXmTAvl{vGW%d9^OTt0rbg|o}s-TSW zUAGB^&pT3|U z!zL6AVjp9Y1KZu=6! z14o>w;oYgYV@#FqLfcmOWebm6@yI%8{uXAfdVGLbqx`_4Q%89&J05IHE}NjKb2eWb NWKMQV2FsA>{{bSxjHUnp literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..74cf86632b56bb7222096c7d8f59400a4fa64c57 GIT binary patch literal 12 QcmZQzV6bOkaBu)&00qMVKmY&$ literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..ac030a9d4018dd553bb0a736b69cf91b5bb6911a GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5=3=9m6 vK+JIPndE&C4dxv9v~U9hBU1{46I>`_)64Jf93gxl0YV`BcSE;IsrzjJ-**?> literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..c79ebe01c240863890d2048ebee5da046c93a90a GIT binary patch literal 9337 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 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 literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..15b75d6ef6bffc336d138d923badb3928b8c4c13 GIT binary patch literal 12 RcmZQzV6bOkU~m8;2LJ>^0RR91 literal 0 HcmV?d00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..7ec9fb4fe2dd21d0a6c324aecd7658fc37cf2326 GIT binary patch literal 151 zcmZQzVB=tvV&Y(AVB}8ZU=(7|U@>L0P?u+5 Date: Tue, 30 Aug 2022 16:50:20 -0700 Subject: [PATCH 03/10] update inference path --- docker/build_artifacts/sagemaker/serve.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/build_artifacts/sagemaker/serve.py b/docker/build_artifacts/sagemaker/serve.py index ef885529..88b2b626 100644 --- a/docker/build_artifacts/sagemaker/serve.py +++ b/docker/build_artifacts/sagemaker/serve.py @@ -28,8 +28,8 @@ JS_INVOCATIONS = "js_content tensorflowServing.invocations" GUNICORN_PING = "proxy_pass http://gunicorn_upstream/ping" GUNICORN_INVOCATIONS = "proxy_pass http://gunicorn_upstream/invocations" -MODEL_DIR = "" if os.environ.get("SAGEMAKER_MULTI_MODEL", "False").lower() == "true" else "model" -CODE_DIR = f"/opt/ml/{MODEL_DIR}/code" +MODEL_DIR = "" if os.environ.get("SAGEMAKER_MULTI_MODEL", "False").lower() == "true" else "model/" +CODE_DIR = f"/opt/ml/{MODEL_DIR}code" PYTHON_LIB_PATH = os.path.join(CODE_DIR, "lib") REQUIREMENTS_PATH = os.path.join(CODE_DIR, "requirements.txt") INFERENCE_PATH = os.path.join(CODE_DIR, "inference.py") From 46328d1058ed4e029bbaf6865dda5489489d8b26 Mon Sep 17 00:00:00 2001 From: Anubhav Sachan Date: Wed, 31 Aug 2022 01:00:01 -0700 Subject: [PATCH 04/10] update inference path --- docker/build_artifacts/sagemaker/python_service.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/build_artifacts/sagemaker/python_service.py b/docker/build_artifacts/sagemaker/python_service.py index 23bdea9a..956708af 100644 --- a/docker/build_artifacts/sagemaker/python_service.py +++ b/docker/build_artifacts/sagemaker/python_service.py @@ -226,8 +226,8 @@ def _handle_load_model_post(self, res, data): # noqa: C901 ) def _import_custom_modules(self, model_name): - inference_script_path = "/opt/ml/models/{}/model/code/inference.py".format(model_name) - python_lib_path = "/opt/ml/models/{}/model/code/lib".format(model_name) + inference_script_path = "/opt/ml/{}/model/code/inference.py".format(model_name) + python_lib_path = "/opt/ml/{}/model/code/lib".format(model_name) if os.path.exists(python_lib_path): log.info("add Python code library path") sys.path.append(python_lib_path) @@ -281,7 +281,7 @@ def _handle_invocation_post(self, req, res, model_name=None): res.status = falcon.HTTP_200 handlers = self._handlers if SAGEMAKER_MULTI_MODEL_ENABLED and model_name in self.model_handlers: - inference_script_path = "/opt/ml/models/{}/model/code/" \ + inference_script_path = "/opt/ml/{}/model/code/" \ "inference.py".format(model_name) log.info("Inference script found at path {}.".format(inference_script_path)) log.info("Inference script exists, importing handlers.") From 195239d7faecee99506b50114af62a46de7a6d9f Mon Sep 17 00:00:00 2001 From: Anubhav Sachan Date: Wed, 31 Aug 2022 12:32:02 -0700 Subject: [PATCH 05/10] update inference paths --- test/integration/local/test_pre_post_processing_mme1.py | 2 +- test/integration/local/test_pre_post_processing_mme2.py | 2 +- test/integration/local/test_pre_post_processing_mme3.py | 2 +- test/integration/local/test_pre_post_processing_mme4.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/integration/local/test_pre_post_processing_mme1.py b/test/integration/local/test_pre_post_processing_mme1.py index 91ac2898..a3ca3037 100644 --- a/test/integration/local/test_pre_post_processing_mme1.py +++ b/test/integration/local/test_pre_post_processing_mme1.py @@ -80,7 +80,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + "url": "/opt/ml/{}/model/{}".format(MODEL_NAME,MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme2.py b/test/integration/local/test_pre_post_processing_mme2.py index c09ff2ee..ef785f53 100644 --- a/test/integration/local/test_pre_post_processing_mme2.py +++ b/test/integration/local/test_pre_post_processing_mme2.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + "url": "/opt/ml/{}/model/{}".format(MODEL_NAME,MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme3.py b/test/integration/local/test_pre_post_processing_mme3.py index b0250fb8..ebc598e0 100644 --- a/test/integration/local/test_pre_post_processing_mme3.py +++ b/test/integration/local/test_pre_post_processing_mme3.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + "url": "//opt/ml/{}/model/{}".format(MODEL_NAME,MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme4.py b/test/integration/local/test_pre_post_processing_mme4.py index fb4f0306..af39afca 100644 --- a/test/integration/local/test_pre_post_processing_mme4.py +++ b/test/integration/local/test_pre_post_processing_mme4.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/models/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + "url": "/opt/ml/{}/model/{}".format(MODEL_NAME,MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES From 0b44c1924a56fe95b569f129ca89eb360f835c46 Mon Sep 17 00:00:00 2001 From: Anubhav Sachan Date: Wed, 21 Sep 2022 15:32:19 -0700 Subject: [PATCH 06/10] Change model path --- .../local/test_pre_post_processing_mme1.py | 2 +- .../local/test_pre_post_processing_mme2.py | 2 +- .../local/test_pre_post_processing_mme3.py | 2 +- .../local/test_pre_post_processing_mme4.py | 2 +- .../{half_plus_three => }/00000123/assets/foo.txt | 0 .../{half_plus_three => }/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../{half_plus_three => }/00000124/assets/foo.txt | 0 .../{half_plus_three => }/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../{half_plus_two => }/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../{half_plus_two => }/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../{half_plus_three => }/00000123/assets/foo.txt | 0 .../{half_plus_three => }/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../{half_plus_three => }/00000124/assets/foo.txt | 0 .../{half_plus_three => }/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../{half_plus_two => }/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../{half_plus_two => }/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../{half_plus_three => }/00000123/assets/foo.txt | 0 .../{half_plus_three => }/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../{half_plus_three => }/00000124/assets/foo.txt | 0 .../{half_plus_three => }/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../{half_plus_two => }/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../{half_plus_two => }/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../{half_plus_three => }/00000123/assets/foo.txt | 0 .../{half_plus_three => }/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../{half_plus_three => }/00000124/assets/foo.txt | 0 .../{half_plus_three => }/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin .../{half_plus_two => }/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000123/variables/variables.index | Bin .../{half_plus_two => }/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../00000124/variables/variables.index | Bin 60 files changed, 4 insertions(+), 4 deletions(-) rename test/resources/mme1/half_plus_three/model/{half_plus_three => }/00000123/assets/foo.txt (100%) rename test/resources/mme1/half_plus_three/model/{half_plus_three => }/00000123/saved_model.pb (100%) rename test/resources/mme1/half_plus_three/model/{half_plus_three => }/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme1/half_plus_three/model/{half_plus_three => }/00000123/variables/variables.index (100%) rename test/resources/mme1/half_plus_three/model/{half_plus_three => }/00000124/assets/foo.txt (100%) rename test/resources/mme1/half_plus_three/model/{half_plus_three => }/00000124/saved_model.pb (100%) rename test/resources/mme1/half_plus_three/model/{half_plus_three => }/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme1/half_plus_three/model/{half_plus_three => }/00000124/variables/variables.index (100%) rename test/resources/mme1/half_plus_two/model/{half_plus_two => }/00000123/saved_model.pb (100%) rename test/resources/mme1/half_plus_two/model/{half_plus_two => }/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme1/half_plus_two/model/{half_plus_two => }/00000123/variables/variables.index (100%) rename test/resources/mme1/half_plus_two/model/{half_plus_two => }/00000124/saved_model.pb (100%) rename test/resources/mme1/half_plus_two/model/{half_plus_two => }/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme1/half_plus_two/model/{half_plus_two => }/00000124/variables/variables.index (100%) rename test/resources/mme2/half_plus_three/model/{half_plus_three => }/00000123/assets/foo.txt (100%) rename test/resources/mme2/half_plus_three/model/{half_plus_three => }/00000123/saved_model.pb (100%) rename test/resources/mme2/half_plus_three/model/{half_plus_three => }/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme2/half_plus_three/model/{half_plus_three => }/00000123/variables/variables.index (100%) rename test/resources/mme2/half_plus_three/model/{half_plus_three => }/00000124/assets/foo.txt (100%) rename test/resources/mme2/half_plus_three/model/{half_plus_three => }/00000124/saved_model.pb (100%) rename test/resources/mme2/half_plus_three/model/{half_plus_three => }/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme2/half_plus_three/model/{half_plus_three => }/00000124/variables/variables.index (100%) rename test/resources/mme2/half_plus_two/model/{half_plus_two => }/00000123/saved_model.pb (100%) rename test/resources/mme2/half_plus_two/model/{half_plus_two => }/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme2/half_plus_two/model/{half_plus_two => }/00000123/variables/variables.index (100%) rename test/resources/mme2/half_plus_two/model/{half_plus_two => }/00000124/saved_model.pb (100%) rename test/resources/mme2/half_plus_two/model/{half_plus_two => }/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme2/half_plus_two/model/{half_plus_two => }/00000124/variables/variables.index (100%) rename test/resources/mme3/half_plus_three/model/{half_plus_three => }/00000123/assets/foo.txt (100%) rename test/resources/mme3/half_plus_three/model/{half_plus_three => }/00000123/saved_model.pb (100%) rename test/resources/mme3/half_plus_three/model/{half_plus_three => }/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme3/half_plus_three/model/{half_plus_three => }/00000123/variables/variables.index (100%) rename test/resources/mme3/half_plus_three/model/{half_plus_three => }/00000124/assets/foo.txt (100%) rename test/resources/mme3/half_plus_three/model/{half_plus_three => }/00000124/saved_model.pb (100%) rename test/resources/mme3/half_plus_three/model/{half_plus_three => }/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme3/half_plus_three/model/{half_plus_three => }/00000124/variables/variables.index (100%) rename test/resources/mme3/half_plus_two/model/{half_plus_two => }/00000123/saved_model.pb (100%) rename test/resources/mme3/half_plus_two/model/{half_plus_two => }/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme3/half_plus_two/model/{half_plus_two => }/00000123/variables/variables.index (100%) rename test/resources/mme3/half_plus_two/model/{half_plus_two => }/00000124/saved_model.pb (100%) rename test/resources/mme3/half_plus_two/model/{half_plus_two => }/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme3/half_plus_two/model/{half_plus_two => }/00000124/variables/variables.index (100%) rename test/resources/mme4/half_plus_three/model/{half_plus_three => }/00000123/assets/foo.txt (100%) rename test/resources/mme4/half_plus_three/model/{half_plus_three => }/00000123/saved_model.pb (100%) rename test/resources/mme4/half_plus_three/model/{half_plus_three => }/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme4/half_plus_three/model/{half_plus_three => }/00000123/variables/variables.index (100%) rename test/resources/mme4/half_plus_three/model/{half_plus_three => }/00000124/assets/foo.txt (100%) rename test/resources/mme4/half_plus_three/model/{half_plus_three => }/00000124/saved_model.pb (100%) rename test/resources/mme4/half_plus_three/model/{half_plus_three => }/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme4/half_plus_three/model/{half_plus_three => }/00000124/variables/variables.index (100%) rename test/resources/mme4/half_plus_two/model/{half_plus_two => }/00000123/saved_model.pb (100%) rename test/resources/mme4/half_plus_two/model/{half_plus_two => }/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme4/half_plus_two/model/{half_plus_two => }/00000123/variables/variables.index (100%) rename test/resources/mme4/half_plus_two/model/{half_plus_two => }/00000124/saved_model.pb (100%) rename test/resources/mme4/half_plus_two/model/{half_plus_two => }/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme4/half_plus_two/model/{half_plus_two => }/00000124/variables/variables.index (100%) diff --git a/test/integration/local/test_pre_post_processing_mme1.py b/test/integration/local/test_pre_post_processing_mme1.py index a3ca3037..b8c47a29 100644 --- a/test/integration/local/test_pre_post_processing_mme1.py +++ b/test/integration/local/test_pre_post_processing_mme1.py @@ -80,7 +80,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + "url": "/opt/ml/{}/model".format(MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme2.py b/test/integration/local/test_pre_post_processing_mme2.py index ef785f53..b8a1cb4e 100644 --- a/test/integration/local/test_pre_post_processing_mme2.py +++ b/test/integration/local/test_pre_post_processing_mme2.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + "url": "/opt/ml/{}/model".format(MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme3.py b/test/integration/local/test_pre_post_processing_mme3.py index ebc598e0..e8d11a10 100644 --- a/test/integration/local/test_pre_post_processing_mme3.py +++ b/test/integration/local/test_pre_post_processing_mme3.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "//opt/ml/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + "url": "/opt/ml/{}/model".format(MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme4.py b/test/integration/local/test_pre_post_processing_mme4.py index af39afca..5499bad0 100644 --- a/test/integration/local/test_pre_post_processing_mme4.py +++ b/test/integration/local/test_pre_post_processing_mme4.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/{}/model/{}".format(MODEL_NAME,MODEL_NAME) + "url": "/opt/ml/{}/model".format(MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme1/half_plus_three/model/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme1/half_plus_three/model/half_plus_three/00000123/assets/foo.txt rename to test/resources/mme1/half_plus_three/model/00000123/assets/foo.txt diff --git a/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme1/half_plus_three/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme1/half_plus_three/model/half_plus_three/00000123/saved_model.pb rename to test/resources/mme1/half_plus_three/model/00000123/saved_model.pb diff --git a/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme1/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme1/half_plus_three/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme1/half_plus_three/model/half_plus_three/00000123/variables/variables.index rename to test/resources/mme1/half_plus_three/model/00000123/variables/variables.index diff --git a/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme1/half_plus_three/model/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme1/half_plus_three/model/half_plus_three/00000124/assets/foo.txt rename to test/resources/mme1/half_plus_three/model/00000124/assets/foo.txt diff --git a/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme1/half_plus_three/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme1/half_plus_three/model/half_plus_three/00000124/saved_model.pb rename to test/resources/mme1/half_plus_three/model/00000124/saved_model.pb diff --git a/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme1/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme1/half_plus_three/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme1/half_plus_three/model/half_plus_three/00000124/variables/variables.index rename to test/resources/mme1/half_plus_three/model/00000124/variables/variables.index diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme1/half_plus_two/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme1/half_plus_two/model/half_plus_two/00000123/saved_model.pb rename to test/resources/mme1/half_plus_two/model/00000123/saved_model.pb diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme1/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme1/half_plus_two/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme1/half_plus_two/model/half_plus_two/00000123/variables/variables.index rename to test/resources/mme1/half_plus_two/model/00000123/variables/variables.index diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/saved_model.pb b/test/resources/mme1/half_plus_two/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme1/half_plus_two/model/half_plus_two/00000124/saved_model.pb rename to test/resources/mme1/half_plus_two/model/00000124/saved_model.pb diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme1/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme1/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme1/half_plus_two/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme1/half_plus_two/model/half_plus_two/00000124/variables/variables.index rename to test/resources/mme1/half_plus_two/model/00000124/variables/variables.index diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme2/half_plus_three/model/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme2/half_plus_three/model/half_plus_three/00000123/assets/foo.txt rename to test/resources/mme2/half_plus_three/model/00000123/assets/foo.txt diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme2/half_plus_three/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme2/half_plus_three/model/half_plus_three/00000123/saved_model.pb rename to test/resources/mme2/half_plus_three/model/00000123/saved_model.pb diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme2/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme2/half_plus_three/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme2/half_plus_three/model/half_plus_three/00000123/variables/variables.index rename to test/resources/mme2/half_plus_three/model/00000123/variables/variables.index diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme2/half_plus_three/model/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme2/half_plus_three/model/half_plus_three/00000124/assets/foo.txt rename to test/resources/mme2/half_plus_three/model/00000124/assets/foo.txt diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme2/half_plus_three/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme2/half_plus_three/model/half_plus_three/00000124/saved_model.pb rename to test/resources/mme2/half_plus_three/model/00000124/saved_model.pb diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme2/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme2/half_plus_three/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme2/half_plus_three/model/half_plus_three/00000124/variables/variables.index rename to test/resources/mme2/half_plus_three/model/00000124/variables/variables.index diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme2/half_plus_two/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme2/half_plus_two/model/half_plus_two/00000123/saved_model.pb rename to test/resources/mme2/half_plus_two/model/00000123/saved_model.pb diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme2/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme2/half_plus_two/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme2/half_plus_two/model/half_plus_two/00000123/variables/variables.index rename to test/resources/mme2/half_plus_two/model/00000123/variables/variables.index diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/saved_model.pb b/test/resources/mme2/half_plus_two/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme2/half_plus_two/model/half_plus_two/00000124/saved_model.pb rename to test/resources/mme2/half_plus_two/model/00000124/saved_model.pb diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme2/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme2/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme2/half_plus_two/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme2/half_plus_two/model/half_plus_two/00000124/variables/variables.index rename to test/resources/mme2/half_plus_two/model/00000124/variables/variables.index diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme3/half_plus_three/model/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme3/half_plus_three/model/half_plus_three/00000123/assets/foo.txt rename to test/resources/mme3/half_plus_three/model/00000123/assets/foo.txt diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme3/half_plus_three/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme3/half_plus_three/model/half_plus_three/00000123/saved_model.pb rename to test/resources/mme3/half_plus_three/model/00000123/saved_model.pb diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme3/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme3/half_plus_three/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme3/half_plus_three/model/half_plus_three/00000123/variables/variables.index rename to test/resources/mme3/half_plus_three/model/00000123/variables/variables.index diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme3/half_plus_three/model/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme3/half_plus_three/model/half_plus_three/00000124/assets/foo.txt rename to test/resources/mme3/half_plus_three/model/00000124/assets/foo.txt diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme3/half_plus_three/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme3/half_plus_three/model/half_plus_three/00000124/saved_model.pb rename to test/resources/mme3/half_plus_three/model/00000124/saved_model.pb diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme3/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme3/half_plus_three/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme3/half_plus_three/model/half_plus_three/00000124/variables/variables.index rename to test/resources/mme3/half_plus_three/model/00000124/variables/variables.index diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme3/half_plus_two/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme3/half_plus_two/model/half_plus_two/00000123/saved_model.pb rename to test/resources/mme3/half_plus_two/model/00000123/saved_model.pb diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme3/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme3/half_plus_two/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme3/half_plus_two/model/half_plus_two/00000123/variables/variables.index rename to test/resources/mme3/half_plus_two/model/00000123/variables/variables.index diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/saved_model.pb b/test/resources/mme3/half_plus_two/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme3/half_plus_two/model/half_plus_two/00000124/saved_model.pb rename to test/resources/mme3/half_plus_two/model/00000124/saved_model.pb diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme3/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme3/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme3/half_plus_two/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme3/half_plus_two/model/half_plus_two/00000124/variables/variables.index rename to test/resources/mme3/half_plus_two/model/00000124/variables/variables.index diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/assets/foo.txt b/test/resources/mme4/half_plus_three/model/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme4/half_plus_three/model/half_plus_three/00000123/assets/foo.txt rename to test/resources/mme4/half_plus_three/model/00000123/assets/foo.txt diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/saved_model.pb b/test/resources/mme4/half_plus_three/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme4/half_plus_three/model/half_plus_three/00000123/saved_model.pb rename to test/resources/mme4/half_plus_three/model/00000123/saved_model.pb diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme4/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.index b/test/resources/mme4/half_plus_three/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme4/half_plus_three/model/half_plus_three/00000123/variables/variables.index rename to test/resources/mme4/half_plus_three/model/00000123/variables/variables.index diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt b/test/resources/mme4/half_plus_three/model/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme4/half_plus_three/model/half_plus_three/00000124/assets/foo.txt rename to test/resources/mme4/half_plus_three/model/00000124/assets/foo.txt diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/saved_model.pb b/test/resources/mme4/half_plus_three/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme4/half_plus_three/model/half_plus_three/00000124/saved_model.pb rename to test/resources/mme4/half_plus_three/model/00000124/saved_model.pb diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme4/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.index b/test/resources/mme4/half_plus_three/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme4/half_plus_three/model/half_plus_three/00000124/variables/variables.index rename to test/resources/mme4/half_plus_three/model/00000124/variables/variables.index diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/saved_model.pb b/test/resources/mme4/half_plus_two/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme4/half_plus_two/model/half_plus_two/00000123/saved_model.pb rename to test/resources/mme4/half_plus_two/model/00000123/saved_model.pb diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme4/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.index b/test/resources/mme4/half_plus_two/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme4/half_plus_two/model/half_plus_two/00000123/variables/variables.index rename to test/resources/mme4/half_plus_two/model/00000123/variables/variables.index diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/saved_model.pb b/test/resources/mme4/half_plus_two/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme4/half_plus_two/model/half_plus_two/00000124/saved_model.pb rename to test/resources/mme4/half_plus_two/model/00000124/saved_model.pb diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme4/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme4/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.index b/test/resources/mme4/half_plus_two/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme4/half_plus_two/model/half_plus_two/00000124/variables/variables.index rename to test/resources/mme4/half_plus_two/model/00000124/variables/variables.index From 50b1d79c896dd2c174e96a0bbf5e9cdc222af623 Mon Sep 17 00:00:00 2001 From: Anubhav Sachan Date: Thu, 22 Sep 2022 10:04:47 -0700 Subject: [PATCH 07/10] Change model path --- docker/build_artifacts/sagemaker/tensorflowServing.js | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/build_artifacts/sagemaker/tensorflowServing.js b/docker/build_artifacts/sagemaker/tensorflowServing.js index 96a00695..807eb43a 100644 --- a/docker/build_artifacts/sagemaker/tensorflowServing.js +++ b/docker/build_artifacts/sagemaker/tensorflowServing.js @@ -68,7 +68,6 @@ function tfs_json_request(r, json) { method: 'POST', body: json } - var accept = r.headersIn.Accept function callback (reply) { var body = reply.responseBody From 002292aa9f547112f8032c9afc4f241f3aa2e377 Mon Sep 17 00:00:00 2001 From: Anubhav Sachan Date: Fri, 23 Sep 2022 11:06:22 -0700 Subject: [PATCH 08/10] Change model path --- docker/build_artifacts/sagemaker/tensorflowServing.js | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/build_artifacts/sagemaker/tensorflowServing.js b/docker/build_artifacts/sagemaker/tensorflowServing.js index 807eb43a..f61a28c2 100644 --- a/docker/build_artifacts/sagemaker/tensorflowServing.js +++ b/docker/build_artifacts/sagemaker/tensorflowServing.js @@ -75,7 +75,6 @@ function tfs_json_request(r, json) { // "fix" broken json escaping in \'instances\' message body = body.replace("\\'instances\\'", "'instances'") } - if (accept != undefined) { var content_types = accept.trim().replace(" ", "").split(",") if (content_types.includes('application/jsonlines') || content_types.includes('application/json')) { From 96346a96c44ce0354d7aef82d76125692f0bb071 Mon Sep 17 00:00:00 2001 From: Anubhav Sachan Date: Wed, 28 Sep 2022 13:02:35 -0700 Subject: [PATCH 09/10] Fix directory structure for inference files and update documentations --- README.md | 18 ++++++++++-------- .../sagemaker/python_service.py | 6 +++--- .../local/test_pre_post_processing_mme1.py | 2 +- .../local/test_pre_post_processing_mme2.py | 2 +- .../local/test_pre_post_processing_mme3.py | 2 +- .../local/test_pre_post_processing_mme4.py | 2 +- .../model/00000123/assets/foo.txt | 0 .../model/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000123/variables/variables.index | Bin .../model/00000124/assets/foo.txt | 0 .../model/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000124/variables/variables.index | Bin .../model/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000123/variables/variables.index | Bin .../model/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000124/variables/variables.index | Bin .../model/00000123/assets/foo.txt | 0 .../model/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000123/variables/variables.index | Bin .../model/00000124/assets/foo.txt | 0 .../model/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000124/variables/variables.index | Bin .../half_plus_three/model/code/inference.py | 0 .../model/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000123/variables/variables.index | Bin .../model/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000124/variables/variables.index | Bin .../half_plus_two/model/code/inference.py | 0 .../model/00000123/assets/foo.txt | 0 .../model/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000123/variables/variables.index | Bin .../model/00000124/assets/foo.txt | 0 .../model/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000124/variables/variables.index | Bin .../models/half_plus_three/model/__init__.py | 0 .../half_plus_three/model/code/__init__.py | 0 .../half_plus_three/model/code/inference.py | 0 .../model/code/lib/__init__.py | 0 .../model/code/lib/dummy_module/__init__.py | 0 .../model/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000123/variables/variables.index | Bin .../model/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000124/variables/variables.index | Bin .../model/00000123/assets/foo.txt | 0 .../model/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000123/variables/variables.index | Bin .../model/00000124/assets/foo.txt | 0 .../model/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000124/variables/variables.index | Bin .../models/half_plus_three/model/__init__.py | 0 .../half_plus_three/model/code/__init__.py | 0 .../half_plus_three/model/code/inference.py | 0 .../model/code/lib/__init__.py | 0 .../model/code/lib/dummy_module/__init__.py | 0 .../model/00000123/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000123/variables/variables.index | Bin .../model/00000124/saved_model.pb | Bin .../variables/variables.data-00000-of-00001 | Bin .../model/00000124/variables/variables.index | Bin 74 files changed, 17 insertions(+), 15 deletions(-) rename test/resources/mme1/{ => models}/half_plus_three/model/00000123/assets/foo.txt (100%) rename test/resources/mme1/{ => models}/half_plus_three/model/00000123/saved_model.pb (100%) rename test/resources/mme1/{ => models}/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme1/{ => models}/half_plus_three/model/00000123/variables/variables.index (100%) rename test/resources/mme1/{ => models}/half_plus_three/model/00000124/assets/foo.txt (100%) rename test/resources/mme1/{ => models}/half_plus_three/model/00000124/saved_model.pb (100%) rename test/resources/mme1/{ => models}/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme1/{ => models}/half_plus_three/model/00000124/variables/variables.index (100%) rename test/resources/mme1/{ => models}/half_plus_two/model/00000123/saved_model.pb (100%) rename test/resources/mme1/{ => models}/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme1/{ => models}/half_plus_two/model/00000123/variables/variables.index (100%) rename test/resources/mme1/{ => models}/half_plus_two/model/00000124/saved_model.pb (100%) rename test/resources/mme1/{ => models}/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme1/{ => models}/half_plus_two/model/00000124/variables/variables.index (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/00000123/assets/foo.txt (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/00000123/saved_model.pb (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/00000123/variables/variables.index (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/00000124/assets/foo.txt (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/00000124/saved_model.pb (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/00000124/variables/variables.index (100%) rename test/resources/mme2/{ => models}/half_plus_three/model/code/inference.py (100%) rename test/resources/mme2/{ => models}/half_plus_two/model/00000123/saved_model.pb (100%) rename test/resources/mme2/{ => models}/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme2/{ => models}/half_plus_two/model/00000123/variables/variables.index (100%) rename test/resources/mme2/{ => models}/half_plus_two/model/00000124/saved_model.pb (100%) rename test/resources/mme2/{ => models}/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme2/{ => models}/half_plus_two/model/00000124/variables/variables.index (100%) rename test/resources/mme2/{ => models}/half_plus_two/model/code/inference.py (100%) rename test/resources/mme3/{ => models}/half_plus_three/model/00000123/assets/foo.txt (100%) rename test/resources/mme3/{ => models}/half_plus_three/model/00000123/saved_model.pb (100%) rename test/resources/mme3/{ => models}/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme3/{ => models}/half_plus_three/model/00000123/variables/variables.index (100%) rename test/resources/mme3/{ => models}/half_plus_three/model/00000124/assets/foo.txt (100%) rename test/resources/mme3/{ => models}/half_plus_three/model/00000124/saved_model.pb (100%) rename test/resources/mme3/{ => models}/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme3/{ => models}/half_plus_three/model/00000124/variables/variables.index (100%) create mode 100644 test/resources/mme3/models/half_plus_three/model/__init__.py create mode 100644 test/resources/mme3/models/half_plus_three/model/code/__init__.py rename test/resources/mme3/{ => models}/half_plus_three/model/code/inference.py (100%) create mode 100644 test/resources/mme3/models/half_plus_three/model/code/lib/__init__.py rename test/resources/mme3/{ => models}/half_plus_three/model/code/lib/dummy_module/__init__.py (100%) rename test/resources/mme3/{ => models}/half_plus_two/model/00000123/saved_model.pb (100%) rename test/resources/mme3/{ => models}/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme3/{ => models}/half_plus_two/model/00000123/variables/variables.index (100%) rename test/resources/mme3/{ => models}/half_plus_two/model/00000124/saved_model.pb (100%) rename test/resources/mme3/{ => models}/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme3/{ => models}/half_plus_two/model/00000124/variables/variables.index (100%) rename test/resources/mme4/{ => models}/half_plus_three/model/00000123/assets/foo.txt (100%) rename test/resources/mme4/{ => models}/half_plus_three/model/00000123/saved_model.pb (100%) rename test/resources/mme4/{ => models}/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme4/{ => models}/half_plus_three/model/00000123/variables/variables.index (100%) rename test/resources/mme4/{ => models}/half_plus_three/model/00000124/assets/foo.txt (100%) rename test/resources/mme4/{ => models}/half_plus_three/model/00000124/saved_model.pb (100%) rename test/resources/mme4/{ => models}/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme4/{ => models}/half_plus_three/model/00000124/variables/variables.index (100%) create mode 100644 test/resources/mme4/models/half_plus_three/model/__init__.py create mode 100644 test/resources/mme4/models/half_plus_three/model/code/__init__.py rename test/resources/mme4/{ => models}/half_plus_three/model/code/inference.py (100%) create mode 100644 test/resources/mme4/models/half_plus_three/model/code/lib/__init__.py rename test/resources/mme4/{ => models}/half_plus_three/model/code/lib/dummy_module/__init__.py (100%) rename test/resources/mme4/{ => models}/half_plus_two/model/00000123/saved_model.pb (100%) rename test/resources/mme4/{ => models}/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme4/{ => models}/half_plus_two/model/00000123/variables/variables.index (100%) rename test/resources/mme4/{ => models}/half_plus_two/model/00000124/saved_model.pb (100%) rename test/resources/mme4/{ => models}/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 (100%) rename test/resources/mme4/{ => models}/half_plus_two/model/00000124/variables/variables.index (100%) diff --git a/README.md b/README.md index e8042719..69bbd1ec 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,8 @@ The container will convert data in these formats to [TensorFlow Serving REST API and will send these requests to the default serving signature of your SavedModel bundle. You can also add customized Python code to process your input and output data. To use this feature, you need to: -1. Add a python file named `inference.py` to the code directory inside your model archive. +1. Add a python file named `inference.py` to the `code` directory inside your model archive. +2. If you want to use a universal `inference.py` file with a multi-model endpoint, then include it in the `code` directory at the s3 URI where the model archives are stored. 2. In `inference.py`, implement either a pair of `input_handler` and `output_handler` functions or a single `handler` function. Note that if `handler` function is implemented, `input_handler` and `output_handler` will be ignored. To implement pre/post-processing handler(s), you will need to make use of the `Context` object created by Python service. The `Context` is a `namedtuple` with following attributes: @@ -357,35 +358,36 @@ def _process_output(data, context): You can also bring in external dependencies to help with your data processing. There are 2 ways to do this: 1. If your model archive contains `code/requirements.txt`, the container will install the Python dependencies at runtime using `pip install -r`. +2. If you invoke a multi-model endpoint, only the universal `requirements.txt` file's Python dependencies will be installed at runtime. Dependencies specified in any `requirements.txt` file present in a model archive will not be installed. 2. If you are working in a network-isolation situation or if you don't want to install dependencies at runtime everytime your Endpoint starts or Batch Transform job runs, you may want to put pre-downloaded dependencies under `code/lib` directory in your model archive, the container will then add the modules to the Python path. Note that if both `code/lib` and `code/requirements.txt` are present in the model archive, the `requirements.txt` will be ignored. Your untarred model directory structure may look like this if you are using `requirements.txt`: - model1 + /opt/ml/models/model1/model |--[model_version_number] |--variables |--saved_model.pb - model2 + /opt/ml/models/model2/model |--[model_version_number] |--assets |--variables |--saved_model.pb - code + /opt/ml/code |--inference.py |--requirements.txt Your untarred model directory structure may look like this if you have downloaded modules under `code/lib`: - model1 + /opt/ml/models/model1/model |--[model_version_number] |--variables |--saved_model.pb - model2 + /opt/ml/models/model2/model |--[model_version_number] |--assets |--variables |--saved_model.pb - code + /opt/ml/code |--lib |--external_module |--inference.py @@ -696,7 +698,7 @@ Another example with of the directory structure of Multi-Model Endpoint with a u |--assets |--variables |--saved_model.pb - code + /opt/ml/code |--requirements.txt |--inference.py ## Contributing diff --git a/docker/build_artifacts/sagemaker/python_service.py b/docker/build_artifacts/sagemaker/python_service.py index 956708af..23bdea9a 100644 --- a/docker/build_artifacts/sagemaker/python_service.py +++ b/docker/build_artifacts/sagemaker/python_service.py @@ -226,8 +226,8 @@ def _handle_load_model_post(self, res, data): # noqa: C901 ) def _import_custom_modules(self, model_name): - inference_script_path = "/opt/ml/{}/model/code/inference.py".format(model_name) - python_lib_path = "/opt/ml/{}/model/code/lib".format(model_name) + inference_script_path = "/opt/ml/models/{}/model/code/inference.py".format(model_name) + python_lib_path = "/opt/ml/models/{}/model/code/lib".format(model_name) if os.path.exists(python_lib_path): log.info("add Python code library path") sys.path.append(python_lib_path) @@ -281,7 +281,7 @@ def _handle_invocation_post(self, req, res, model_name=None): res.status = falcon.HTTP_200 handlers = self._handlers if SAGEMAKER_MULTI_MODEL_ENABLED and model_name in self.model_handlers: - inference_script_path = "/opt/ml/{}/model/code/" \ + inference_script_path = "/opt/ml/models/{}/model/code/" \ "inference.py".format(model_name) log.info("Inference script found at path {}.".format(inference_script_path)) log.info("Inference script exists, importing handlers.") diff --git a/test/integration/local/test_pre_post_processing_mme1.py b/test/integration/local/test_pre_post_processing_mme1.py index b8c47a29..6197af90 100644 --- a/test/integration/local/test_pre_post_processing_mme1.py +++ b/test/integration/local/test_pre_post_processing_mme1.py @@ -80,7 +80,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/{}/model".format(MODEL_NAME) + "url": "/opt/ml/models/{}/model".format(MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme2.py b/test/integration/local/test_pre_post_processing_mme2.py index b8a1cb4e..901902f7 100644 --- a/test/integration/local/test_pre_post_processing_mme2.py +++ b/test/integration/local/test_pre_post_processing_mme2.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/{}/model".format(MODEL_NAME) + "url": "/opt/ml/models/{}/model".format(MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme3.py b/test/integration/local/test_pre_post_processing_mme3.py index e8d11a10..7356da8e 100644 --- a/test/integration/local/test_pre_post_processing_mme3.py +++ b/test/integration/local/test_pre_post_processing_mme3.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/{}/model".format(MODEL_NAME) + "url": "/opt/ml/models/{}/model".format(MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/integration/local/test_pre_post_processing_mme4.py b/test/integration/local/test_pre_post_processing_mme4.py index 5499bad0..622f4618 100644 --- a/test/integration/local/test_pre_post_processing_mme4.py +++ b/test/integration/local/test_pre_post_processing_mme4.py @@ -81,7 +81,7 @@ def models(): for MODEL_NAME in MODEL_NAMES: model_data = { "model_name": MODEL_NAME, - "url": "/opt/ml/{}/model".format(MODEL_NAME) + "url": "/opt/ml/models/{}/model".format(MODEL_NAME) } make_load_model_request(json.dumps(model_data)) return MODEL_NAMES diff --git a/test/resources/mme1/half_plus_three/model/00000123/assets/foo.txt b/test/resources/mme1/models/half_plus_three/model/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme1/half_plus_three/model/00000123/assets/foo.txt rename to test/resources/mme1/models/half_plus_three/model/00000123/assets/foo.txt diff --git a/test/resources/mme1/half_plus_three/model/00000123/saved_model.pb b/test/resources/mme1/models/half_plus_three/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme1/half_plus_three/model/00000123/saved_model.pb rename to test/resources/mme1/models/half_plus_three/model/00000123/saved_model.pb diff --git a/test/resources/mme1/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme1/models/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme1/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme1/models/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme1/half_plus_three/model/00000123/variables/variables.index b/test/resources/mme1/models/half_plus_three/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme1/half_plus_three/model/00000123/variables/variables.index rename to test/resources/mme1/models/half_plus_three/model/00000123/variables/variables.index diff --git a/test/resources/mme1/half_plus_three/model/00000124/assets/foo.txt b/test/resources/mme1/models/half_plus_three/model/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme1/half_plus_three/model/00000124/assets/foo.txt rename to test/resources/mme1/models/half_plus_three/model/00000124/assets/foo.txt diff --git a/test/resources/mme1/half_plus_three/model/00000124/saved_model.pb b/test/resources/mme1/models/half_plus_three/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme1/half_plus_three/model/00000124/saved_model.pb rename to test/resources/mme1/models/half_plus_three/model/00000124/saved_model.pb diff --git a/test/resources/mme1/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme1/models/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme1/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme1/models/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme1/half_plus_three/model/00000124/variables/variables.index b/test/resources/mme1/models/half_plus_three/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme1/half_plus_three/model/00000124/variables/variables.index rename to test/resources/mme1/models/half_plus_three/model/00000124/variables/variables.index diff --git a/test/resources/mme1/half_plus_two/model/00000123/saved_model.pb b/test/resources/mme1/models/half_plus_two/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme1/half_plus_two/model/00000123/saved_model.pb rename to test/resources/mme1/models/half_plus_two/model/00000123/saved_model.pb diff --git a/test/resources/mme1/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme1/models/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme1/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme1/models/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme1/half_plus_two/model/00000123/variables/variables.index b/test/resources/mme1/models/half_plus_two/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme1/half_plus_two/model/00000123/variables/variables.index rename to test/resources/mme1/models/half_plus_two/model/00000123/variables/variables.index diff --git a/test/resources/mme1/half_plus_two/model/00000124/saved_model.pb b/test/resources/mme1/models/half_plus_two/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme1/half_plus_two/model/00000124/saved_model.pb rename to test/resources/mme1/models/half_plus_two/model/00000124/saved_model.pb diff --git a/test/resources/mme1/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme1/models/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme1/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme1/models/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme1/half_plus_two/model/00000124/variables/variables.index b/test/resources/mme1/models/half_plus_two/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme1/half_plus_two/model/00000124/variables/variables.index rename to test/resources/mme1/models/half_plus_two/model/00000124/variables/variables.index diff --git a/test/resources/mme2/half_plus_three/model/00000123/assets/foo.txt b/test/resources/mme2/models/half_plus_three/model/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme2/half_plus_three/model/00000123/assets/foo.txt rename to test/resources/mme2/models/half_plus_three/model/00000123/assets/foo.txt diff --git a/test/resources/mme2/half_plus_three/model/00000123/saved_model.pb b/test/resources/mme2/models/half_plus_three/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme2/half_plus_three/model/00000123/saved_model.pb rename to test/resources/mme2/models/half_plus_three/model/00000123/saved_model.pb diff --git a/test/resources/mme2/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme2/models/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme2/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme2/models/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme2/half_plus_three/model/00000123/variables/variables.index b/test/resources/mme2/models/half_plus_three/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme2/half_plus_three/model/00000123/variables/variables.index rename to test/resources/mme2/models/half_plus_three/model/00000123/variables/variables.index diff --git a/test/resources/mme2/half_plus_three/model/00000124/assets/foo.txt b/test/resources/mme2/models/half_plus_three/model/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme2/half_plus_three/model/00000124/assets/foo.txt rename to test/resources/mme2/models/half_plus_three/model/00000124/assets/foo.txt diff --git a/test/resources/mme2/half_plus_three/model/00000124/saved_model.pb b/test/resources/mme2/models/half_plus_three/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme2/half_plus_three/model/00000124/saved_model.pb rename to test/resources/mme2/models/half_plus_three/model/00000124/saved_model.pb diff --git a/test/resources/mme2/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme2/models/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme2/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme2/models/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme2/half_plus_three/model/00000124/variables/variables.index b/test/resources/mme2/models/half_plus_three/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme2/half_plus_three/model/00000124/variables/variables.index rename to test/resources/mme2/models/half_plus_three/model/00000124/variables/variables.index diff --git a/test/resources/mme2/half_plus_three/model/code/inference.py b/test/resources/mme2/models/half_plus_three/model/code/inference.py similarity index 100% rename from test/resources/mme2/half_plus_three/model/code/inference.py rename to test/resources/mme2/models/half_plus_three/model/code/inference.py diff --git a/test/resources/mme2/half_plus_two/model/00000123/saved_model.pb b/test/resources/mme2/models/half_plus_two/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme2/half_plus_two/model/00000123/saved_model.pb rename to test/resources/mme2/models/half_plus_two/model/00000123/saved_model.pb diff --git a/test/resources/mme2/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme2/models/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme2/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme2/models/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme2/half_plus_two/model/00000123/variables/variables.index b/test/resources/mme2/models/half_plus_two/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme2/half_plus_two/model/00000123/variables/variables.index rename to test/resources/mme2/models/half_plus_two/model/00000123/variables/variables.index diff --git a/test/resources/mme2/half_plus_two/model/00000124/saved_model.pb b/test/resources/mme2/models/half_plus_two/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme2/half_plus_two/model/00000124/saved_model.pb rename to test/resources/mme2/models/half_plus_two/model/00000124/saved_model.pb diff --git a/test/resources/mme2/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme2/models/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme2/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme2/models/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme2/half_plus_two/model/00000124/variables/variables.index b/test/resources/mme2/models/half_plus_two/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme2/half_plus_two/model/00000124/variables/variables.index rename to test/resources/mme2/models/half_plus_two/model/00000124/variables/variables.index diff --git a/test/resources/mme2/half_plus_two/model/code/inference.py b/test/resources/mme2/models/half_plus_two/model/code/inference.py similarity index 100% rename from test/resources/mme2/half_plus_two/model/code/inference.py rename to test/resources/mme2/models/half_plus_two/model/code/inference.py diff --git a/test/resources/mme3/half_plus_three/model/00000123/assets/foo.txt b/test/resources/mme3/models/half_plus_three/model/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme3/half_plus_three/model/00000123/assets/foo.txt rename to test/resources/mme3/models/half_plus_three/model/00000123/assets/foo.txt diff --git a/test/resources/mme3/half_plus_three/model/00000123/saved_model.pb b/test/resources/mme3/models/half_plus_three/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme3/half_plus_three/model/00000123/saved_model.pb rename to test/resources/mme3/models/half_plus_three/model/00000123/saved_model.pb diff --git a/test/resources/mme3/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme3/models/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme3/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme3/models/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme3/half_plus_three/model/00000123/variables/variables.index b/test/resources/mme3/models/half_plus_three/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme3/half_plus_three/model/00000123/variables/variables.index rename to test/resources/mme3/models/half_plus_three/model/00000123/variables/variables.index diff --git a/test/resources/mme3/half_plus_three/model/00000124/assets/foo.txt b/test/resources/mme3/models/half_plus_three/model/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme3/half_plus_three/model/00000124/assets/foo.txt rename to test/resources/mme3/models/half_plus_three/model/00000124/assets/foo.txt diff --git a/test/resources/mme3/half_plus_three/model/00000124/saved_model.pb b/test/resources/mme3/models/half_plus_three/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme3/half_plus_three/model/00000124/saved_model.pb rename to test/resources/mme3/models/half_plus_three/model/00000124/saved_model.pb diff --git a/test/resources/mme3/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme3/models/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme3/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme3/models/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme3/half_plus_three/model/00000124/variables/variables.index b/test/resources/mme3/models/half_plus_three/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme3/half_plus_three/model/00000124/variables/variables.index rename to test/resources/mme3/models/half_plus_three/model/00000124/variables/variables.index diff --git a/test/resources/mme3/models/half_plus_three/model/__init__.py b/test/resources/mme3/models/half_plus_three/model/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/resources/mme3/models/half_plus_three/model/code/__init__.py b/test/resources/mme3/models/half_plus_three/model/code/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/resources/mme3/half_plus_three/model/code/inference.py b/test/resources/mme3/models/half_plus_three/model/code/inference.py similarity index 100% rename from test/resources/mme3/half_plus_three/model/code/inference.py rename to test/resources/mme3/models/half_plus_three/model/code/inference.py diff --git a/test/resources/mme3/models/half_plus_three/model/code/lib/__init__.py b/test/resources/mme3/models/half_plus_three/model/code/lib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py b/test/resources/mme3/models/half_plus_three/model/code/lib/dummy_module/__init__.py similarity index 100% rename from test/resources/mme3/half_plus_three/model/code/lib/dummy_module/__init__.py rename to test/resources/mme3/models/half_plus_three/model/code/lib/dummy_module/__init__.py diff --git a/test/resources/mme3/half_plus_two/model/00000123/saved_model.pb b/test/resources/mme3/models/half_plus_two/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme3/half_plus_two/model/00000123/saved_model.pb rename to test/resources/mme3/models/half_plus_two/model/00000123/saved_model.pb diff --git a/test/resources/mme3/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme3/models/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme3/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme3/models/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme3/half_plus_two/model/00000123/variables/variables.index b/test/resources/mme3/models/half_plus_two/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme3/half_plus_two/model/00000123/variables/variables.index rename to test/resources/mme3/models/half_plus_two/model/00000123/variables/variables.index diff --git a/test/resources/mme3/half_plus_two/model/00000124/saved_model.pb b/test/resources/mme3/models/half_plus_two/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme3/half_plus_two/model/00000124/saved_model.pb rename to test/resources/mme3/models/half_plus_two/model/00000124/saved_model.pb diff --git a/test/resources/mme3/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme3/models/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme3/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme3/models/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme3/half_plus_two/model/00000124/variables/variables.index b/test/resources/mme3/models/half_plus_two/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme3/half_plus_two/model/00000124/variables/variables.index rename to test/resources/mme3/models/half_plus_two/model/00000124/variables/variables.index diff --git a/test/resources/mme4/half_plus_three/model/00000123/assets/foo.txt b/test/resources/mme4/models/half_plus_three/model/00000123/assets/foo.txt similarity index 100% rename from test/resources/mme4/half_plus_three/model/00000123/assets/foo.txt rename to test/resources/mme4/models/half_plus_three/model/00000123/assets/foo.txt diff --git a/test/resources/mme4/half_plus_three/model/00000123/saved_model.pb b/test/resources/mme4/models/half_plus_three/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme4/half_plus_three/model/00000123/saved_model.pb rename to test/resources/mme4/models/half_plus_three/model/00000123/saved_model.pb diff --git a/test/resources/mme4/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme4/models/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme4/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme4/models/half_plus_three/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme4/half_plus_three/model/00000123/variables/variables.index b/test/resources/mme4/models/half_plus_three/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme4/half_plus_three/model/00000123/variables/variables.index rename to test/resources/mme4/models/half_plus_three/model/00000123/variables/variables.index diff --git a/test/resources/mme4/half_plus_three/model/00000124/assets/foo.txt b/test/resources/mme4/models/half_plus_three/model/00000124/assets/foo.txt similarity index 100% rename from test/resources/mme4/half_plus_three/model/00000124/assets/foo.txt rename to test/resources/mme4/models/half_plus_three/model/00000124/assets/foo.txt diff --git a/test/resources/mme4/half_plus_three/model/00000124/saved_model.pb b/test/resources/mme4/models/half_plus_three/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme4/half_plus_three/model/00000124/saved_model.pb rename to test/resources/mme4/models/half_plus_three/model/00000124/saved_model.pb diff --git a/test/resources/mme4/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme4/models/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme4/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme4/models/half_plus_three/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme4/half_plus_three/model/00000124/variables/variables.index b/test/resources/mme4/models/half_plus_three/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme4/half_plus_three/model/00000124/variables/variables.index rename to test/resources/mme4/models/half_plus_three/model/00000124/variables/variables.index diff --git a/test/resources/mme4/models/half_plus_three/model/__init__.py b/test/resources/mme4/models/half_plus_three/model/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/resources/mme4/models/half_plus_three/model/code/__init__.py b/test/resources/mme4/models/half_plus_three/model/code/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/resources/mme4/half_plus_three/model/code/inference.py b/test/resources/mme4/models/half_plus_three/model/code/inference.py similarity index 100% rename from test/resources/mme4/half_plus_three/model/code/inference.py rename to test/resources/mme4/models/half_plus_three/model/code/inference.py diff --git a/test/resources/mme4/models/half_plus_three/model/code/lib/__init__.py b/test/resources/mme4/models/half_plus_three/model/code/lib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/resources/mme4/half_plus_three/model/code/lib/dummy_module/__init__.py b/test/resources/mme4/models/half_plus_three/model/code/lib/dummy_module/__init__.py similarity index 100% rename from test/resources/mme4/half_plus_three/model/code/lib/dummy_module/__init__.py rename to test/resources/mme4/models/half_plus_three/model/code/lib/dummy_module/__init__.py diff --git a/test/resources/mme4/half_plus_two/model/00000123/saved_model.pb b/test/resources/mme4/models/half_plus_two/model/00000123/saved_model.pb similarity index 100% rename from test/resources/mme4/half_plus_two/model/00000123/saved_model.pb rename to test/resources/mme4/models/half_plus_two/model/00000123/saved_model.pb diff --git a/test/resources/mme4/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 b/test/resources/mme4/models/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme4/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 rename to test/resources/mme4/models/half_plus_two/model/00000123/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme4/half_plus_two/model/00000123/variables/variables.index b/test/resources/mme4/models/half_plus_two/model/00000123/variables/variables.index similarity index 100% rename from test/resources/mme4/half_plus_two/model/00000123/variables/variables.index rename to test/resources/mme4/models/half_plus_two/model/00000123/variables/variables.index diff --git a/test/resources/mme4/half_plus_two/model/00000124/saved_model.pb b/test/resources/mme4/models/half_plus_two/model/00000124/saved_model.pb similarity index 100% rename from test/resources/mme4/half_plus_two/model/00000124/saved_model.pb rename to test/resources/mme4/models/half_plus_two/model/00000124/saved_model.pb diff --git a/test/resources/mme4/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 b/test/resources/mme4/models/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 similarity index 100% rename from test/resources/mme4/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 rename to test/resources/mme4/models/half_plus_two/model/00000124/variables/variables.data-00000-of-00001 diff --git a/test/resources/mme4/half_plus_two/model/00000124/variables/variables.index b/test/resources/mme4/models/half_plus_two/model/00000124/variables/variables.index similarity index 100% rename from test/resources/mme4/half_plus_two/model/00000124/variables/variables.index rename to test/resources/mme4/models/half_plus_two/model/00000124/variables/variables.index From 00ef7fd048c86a53f1a4821add76512627129cd2 Mon Sep 17 00:00:00 2001 From: Anubhav Sachan Date: Tue, 10 Jan 2023 15:01:41 -0800 Subject: [PATCH 10/10] Updated README file --- README.md | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 69bbd1ec..a5fd1262 100644 --- a/README.md +++ b/README.md @@ -363,31 +363,33 @@ You can also bring in external dependencies to help with your data processing. T Your untarred model directory structure may look like this if you are using `requirements.txt`: - /opt/ml/models/model1/model + model1 |--[model_version_number] + |--assets |--variables |--saved_model.pb - /opt/ml/models/model2/model + model2 |--[model_version_number] |--assets |--variables |--saved_model.pb - /opt/ml/code + code |--inference.py |--requirements.txt Your untarred model directory structure may look like this if you have downloaded modules under `code/lib`: - /opt/ml/models/model1/model + model1 |--[model_version_number] + |--assets |--variables |--saved_model.pb - /opt/ml/models/model2/model + model2 |--[model_version_number] |--assets |--variables |--saved_model.pb - /opt/ml/code + code |--lib |--external_module |--inference.py @@ -674,11 +676,12 @@ For example, if the ``SAGEMAKER_SAFE_PORT_RANGE`` is between 9000 to 9999, the m ### Using Multi-Model Endpoint with Pre/Post-Processing Multi-Model Endpoint can be used together with Pre/Post-Processing. Each model can either have its own ``inference.py`` or use a universal ``inference.py``. If both model-specific and universal ``inference.py`` files are provided, then the model-specific ``inference.py`` file is used. If both files are absent, then the default handlers will be used. An example of the directory structure of Multi-Model Endpoint with a model-specific ``inference.py`` file would look like this: - /opt/ml/models/model1/model + model1 |--[model_version_number] + |--assets |--variables |--saved_model.pb - /opt/ml/models/model2/model + model2 |--[model_version_number] |--assets |--variables @@ -689,16 +692,17 @@ Multi-Model Endpoint can be used together with Pre/Post-Processing. Each model c |--inference.py Another example with of the directory structure of Multi-Model Endpoint with a universal ``inference.py`` file is as follows: - /opt/ml/models/model1/model + model1 |--[model_version_number] + |--assets |--variables |--saved_model.pb - /opt/ml/models/model2/model + model2 |--[model_version_number] |--assets |--variables |--saved_model.pb - /opt/ml/code + code |--requirements.txt |--inference.py ## Contributing