add tfs container support - #460

Merged
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs
Nov 7, 2018
Merged

add tfs container support#460
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs

Conversation

@jesterhazy

@jesterhazyjesterhazy commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

Description of changes:

add support for sagemaker-tfs inference container

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have updated the changelog with a description of my changes (if appropriate)
  • I have updated any necessary documentation (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-io

codecov-io commented Nov 6, 2018

Copy link
Copy Markdown

Codecov Report

Merging #460 into master will increase coverage by 0.08%.
The diff coverage is 97.95%.

Impacted file tree graph

@@ Coverage Diff @@## master #460 +/- ##
==========================================
+ Coverage 93.77% 93.86% +0.08% 
==========================================
Files 55 56 +1 Lines 4114 4190 +76 ==========================================
+ Hits 3858 3933 +75 - Misses 256 257 +1
Impacted FilesCoverage Δ
src/sagemaker/predictor.py96.77% <100%> (+0.17%)⬆️
src/sagemaker/tensorflow/estimator.py93.83% <95%> (+0.26%)⬆️
src/sagemaker/tensorflow/serving.py98.38% <98.38%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 868f81b...61dd059. Read the comment docs.

owen-t
owen-t previously approved these changes Nov 6, 2018

@owen-towen-t left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider including Readme updates as well.

Comment threadsrc/sagemaker/tensorflow/estimator.py
Comment threadsrc/sagemaker/predictor.py Outdated
If a serializer was specified when creating the RealTimePredictor, the result of the
serializer is sent as input data. Otherwise the data must be sequence of bytes, and
the predict method then sends the bytes in the request body as is.
initial_args (dict[str,str]): Optional. Initial request arguments. Default is None.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify more this docstring argument.

Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/tensorflow/__init__.py Outdated

from sagemaker.tensorflow.estimator import TensorFlow # noqa: E402, F401
from sagemaker.tensorflow.model import TensorFlowModel, TensorFlowPredictor # noqa: E402, F401
from sagemaker.tensorflow.tfs import TFSModel, TFSPredictor # noqa: E402, F401

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid acronyms to keep the same pattern of the SDK

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TensorFlowServingModel' is unwieldy, and ambiguous since TensorFlowModel also refers to a kind of TensorFlow Serving model. TFS is well aligned with the module name, and the container side package name.

Another option... just calling them Model and Predictor (sagemaker.tensorflow.tfs.Model etc), but this invites collision with sagemaker.Model etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about sagemaker.tesorflow.serving.Model or sagemaker.tensorflow_serving.Model?

Collision should not happen if we are importing modules not classes like specified in the style guide.

Comment threadCHANGELOG.rst Outdated
1.14.0-dev
==========

* add support for sagemaker-tfs container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow correct changelog format.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

name=self._current_job_name,
framework_version=self.framework_version,
sagemaker_session=self.sagemaker_session,
vpc_config=self.get_vpc_config(vpc_config_override))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing container_log_level?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

from sagemaker import Model, RealTimePredictor
from sagemaker.content_types import CONTENT_TYPE_JSON
from sagemaker.fw_utils import create_image_uri
from sagemaker.predictor import json_serializer, json_deserializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from google python style guide -> import modules not functions and classes.

attributes.append('tfs-model-name={}'.format(model_name))
if model_version:
attributes.append('tfs-model-version={}'.format(model_version))
self._model_attributes = ','.join(attributes) if attributes else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an empty array to represent an empty list of model attributes instead of None?

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated


class TFSModel(Model):
FRAMEWORK_NAME = 'tfs'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that other classes use dunders instead of a constant, although I Iike your style better and matches the conventions https://github.com/google/styleguide/blob/gh-pages/pyguide.md#3164-guidelines-derived-from-guidos-recommendations

nit: consider leaving it at module level

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dictionaries are not constants in Python.

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated
return self.env

env = dict(self.env)
env['SAGEMAKER_TFS_NGINX_LOGLEVEL'] = TFSModel.LOG_LEVEL_MAP[self._container_log_level]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a constant for this key.

# reuse standard image uri function, then strip unwanted python component
region_name = self.sagemaker_session.boto_region_name
image = create_image_uri(region_name, TFSModel.FRAMEWORK_NAME, instance_type,
self._framework_version, 'py3')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is to change create image uri instead of reusing and striping it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of fussy behavior in create_image_uri. it would be easy to fall out of sync

with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
model = TFSModel(model_data, 'SageMakerRole', framework_version=tf_full_version)
predictor = model.deploy(1, 'ml.c5.xlarge', endpoint_name=endpoint_name)
yield predictor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test setup

serializer=sagemaker.predictor.csv_serializer)

result = predictor.predict(input_data)
assert expected_result == result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing test cases for errors and empty requests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • handled in unit tests and in container package tests
  • also this is generic predictor / serializer behavior that is well covered by other tests

@jesterhazy
jesterhazy merged commit b6c9b0c into aws:masterNov 7, 2018
@jesterhazy
jesterhazy deleted the je-tfs branch December 9, 2018 19:37
Evan-W-ang added a commit to Evan-W-ang/sagemaker-python-sdk that referenced this pull request Jun 8, 2026
* add tensorflow serving container support
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jesterhazy@codecov-io@mvsusp@owen-t
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

add tfs container support - #460

Merged
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs
Nov 7, 2018
Merged

add tfs container support#460
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs

Conversation

@jesterhazy

@jesterhazyjesterhazy commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

Description of changes:

add support for sagemaker-tfs inference container

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have updated the changelog with a description of my changes (if appropriate)
  • I have updated any necessary documentation (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-io

codecov-io commented Nov 6, 2018

Copy link
Copy Markdown

Codecov Report

Merging #460 into master will increase coverage by 0.08%.
The diff coverage is 97.95%.

Impacted file tree graph

@@ Coverage Diff @@## master #460 +/- ##
==========================================
+ Coverage 93.77% 93.86% +0.08% 
==========================================
Files 55 56 +1 Lines 4114 4190 +76 ==========================================
+ Hits 3858 3933 +75 - Misses 256 257 +1
Impacted FilesCoverage Δ
src/sagemaker/predictor.py96.77% <100%> (+0.17%)⬆️
src/sagemaker/tensorflow/estimator.py93.83% <95%> (+0.26%)⬆️
src/sagemaker/tensorflow/serving.py98.38% <98.38%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 868f81b...61dd059. Read the comment docs.

owen-t
owen-t previously approved these changes Nov 6, 2018

@owen-towen-t left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider including Readme updates as well.

Comment threadsrc/sagemaker/tensorflow/estimator.py
Comment threadsrc/sagemaker/predictor.py Outdated
If a serializer was specified when creating the RealTimePredictor, the result of the
serializer is sent as input data. Otherwise the data must be sequence of bytes, and
the predict method then sends the bytes in the request body as is.
initial_args (dict[str,str]): Optional. Initial request arguments. Default is None.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify more this docstring argument.

Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/tensorflow/__init__.py Outdated

from sagemaker.tensorflow.estimator import TensorFlow # noqa: E402, F401
from sagemaker.tensorflow.model import TensorFlowModel, TensorFlowPredictor # noqa: E402, F401
from sagemaker.tensorflow.tfs import TFSModel, TFSPredictor # noqa: E402, F401

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid acronyms to keep the same pattern of the SDK

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TensorFlowServingModel' is unwieldy, and ambiguous since TensorFlowModel also refers to a kind of TensorFlow Serving model. TFS is well aligned with the module name, and the container side package name.

Another option... just calling them Model and Predictor (sagemaker.tensorflow.tfs.Model etc), but this invites collision with sagemaker.Model etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about sagemaker.tesorflow.serving.Model or sagemaker.tensorflow_serving.Model?

Collision should not happen if we are importing modules not classes like specified in the style guide.

Comment threadCHANGELOG.rst Outdated
1.14.0-dev
==========

* add support for sagemaker-tfs container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow correct changelog format.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

name=self._current_job_name,
framework_version=self.framework_version,
sagemaker_session=self.sagemaker_session,
vpc_config=self.get_vpc_config(vpc_config_override))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing container_log_level?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

from sagemaker import Model, RealTimePredictor
from sagemaker.content_types import CONTENT_TYPE_JSON
from sagemaker.fw_utils import create_image_uri
from sagemaker.predictor import json_serializer, json_deserializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from google python style guide -> import modules not functions and classes.

attributes.append('tfs-model-name={}'.format(model_name))
if model_version:
attributes.append('tfs-model-version={}'.format(model_version))
self._model_attributes = ','.join(attributes) if attributes else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an empty array to represent an empty list of model attributes instead of None?

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated


class TFSModel(Model):
FRAMEWORK_NAME = 'tfs'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that other classes use dunders instead of a constant, although I Iike your style better and matches the conventions https://github.com/google/styleguide/blob/gh-pages/pyguide.md#3164-guidelines-derived-from-guidos-recommendations

nit: consider leaving it at module level

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dictionaries are not constants in Python.

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated
return self.env

env = dict(self.env)
env['SAGEMAKER_TFS_NGINX_LOGLEVEL'] = TFSModel.LOG_LEVEL_MAP[self._container_log_level]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a constant for this key.

# reuse standard image uri function, then strip unwanted python component
region_name = self.sagemaker_session.boto_region_name
image = create_image_uri(region_name, TFSModel.FRAMEWORK_NAME, instance_type,
self._framework_version, 'py3')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is to change create image uri instead of reusing and striping it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of fussy behavior in create_image_uri. it would be easy to fall out of sync

with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
model = TFSModel(model_data, 'SageMakerRole', framework_version=tf_full_version)
predictor = model.deploy(1, 'ml.c5.xlarge', endpoint_name=endpoint_name)
yield predictor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test setup

serializer=sagemaker.predictor.csv_serializer)

result = predictor.predict(input_data)
assert expected_result == result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing test cases for errors and empty requests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • handled in unit tests and in container package tests
  • also this is generic predictor / serializer behavior that is well covered by other tests

@jesterhazy
jesterhazy merged commit b6c9b0c into aws:masterNov 7, 2018
@jesterhazy
jesterhazy deleted the je-tfs branch December 9, 2018 19:37
Evan-W-ang added a commit to Evan-W-ang/sagemaker-python-sdk that referenced this pull request Jun 8, 2026
* add tensorflow serving container support
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jesterhazy@codecov-io@mvsusp@owen-t
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

add tfs container support - #460

Merged
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs
Nov 7, 2018
Merged

add tfs container support#460
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs

Conversation

@jesterhazy

@jesterhazyjesterhazy commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

Description of changes:

add support for sagemaker-tfs inference container

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have updated the changelog with a description of my changes (if appropriate)
  • I have updated any necessary documentation (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-io

codecov-io commented Nov 6, 2018

Copy link
Copy Markdown

Codecov Report

Merging #460 into master will increase coverage by 0.08%.
The diff coverage is 97.95%.

Impacted file tree graph

@@ Coverage Diff @@## master #460 +/- ##
==========================================
+ Coverage 93.77% 93.86% +0.08% 
==========================================
Files 55 56 +1 Lines 4114 4190 +76 ==========================================
+ Hits 3858 3933 +75 - Misses 256 257 +1
Impacted FilesCoverage Δ
src/sagemaker/predictor.py96.77% <100%> (+0.17%)⬆️
src/sagemaker/tensorflow/estimator.py93.83% <95%> (+0.26%)⬆️
src/sagemaker/tensorflow/serving.py98.38% <98.38%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 868f81b...61dd059. Read the comment docs.

owen-t
owen-t previously approved these changes Nov 6, 2018

@owen-towen-t left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider including Readme updates as well.

Comment threadsrc/sagemaker/tensorflow/estimator.py
Comment threadsrc/sagemaker/predictor.py Outdated
If a serializer was specified when creating the RealTimePredictor, the result of the
serializer is sent as input data. Otherwise the data must be sequence of bytes, and
the predict method then sends the bytes in the request body as is.
initial_args (dict[str,str]): Optional. Initial request arguments. Default is None.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify more this docstring argument.

Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/tensorflow/__init__.py Outdated

from sagemaker.tensorflow.estimator import TensorFlow # noqa: E402, F401
from sagemaker.tensorflow.model import TensorFlowModel, TensorFlowPredictor # noqa: E402, F401
from sagemaker.tensorflow.tfs import TFSModel, TFSPredictor # noqa: E402, F401

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid acronyms to keep the same pattern of the SDK

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TensorFlowServingModel' is unwieldy, and ambiguous since TensorFlowModel also refers to a kind of TensorFlow Serving model. TFS is well aligned with the module name, and the container side package name.

Another option... just calling them Model and Predictor (sagemaker.tensorflow.tfs.Model etc), but this invites collision with sagemaker.Model etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about sagemaker.tesorflow.serving.Model or sagemaker.tensorflow_serving.Model?

Collision should not happen if we are importing modules not classes like specified in the style guide.

Comment threadCHANGELOG.rst Outdated
1.14.0-dev
==========

* add support for sagemaker-tfs container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow correct changelog format.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

name=self._current_job_name,
framework_version=self.framework_version,
sagemaker_session=self.sagemaker_session,
vpc_config=self.get_vpc_config(vpc_config_override))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing container_log_level?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

from sagemaker import Model, RealTimePredictor
from sagemaker.content_types import CONTENT_TYPE_JSON
from sagemaker.fw_utils import create_image_uri
from sagemaker.predictor import json_serializer, json_deserializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from google python style guide -> import modules not functions and classes.

attributes.append('tfs-model-name={}'.format(model_name))
if model_version:
attributes.append('tfs-model-version={}'.format(model_version))
self._model_attributes = ','.join(attributes) if attributes else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an empty array to represent an empty list of model attributes instead of None?

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated


class TFSModel(Model):
FRAMEWORK_NAME = 'tfs'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that other classes use dunders instead of a constant, although I Iike your style better and matches the conventions https://github.com/google/styleguide/blob/gh-pages/pyguide.md#3164-guidelines-derived-from-guidos-recommendations

nit: consider leaving it at module level

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dictionaries are not constants in Python.

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated
return self.env

env = dict(self.env)
env['SAGEMAKER_TFS_NGINX_LOGLEVEL'] = TFSModel.LOG_LEVEL_MAP[self._container_log_level]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a constant for this key.

# reuse standard image uri function, then strip unwanted python component
region_name = self.sagemaker_session.boto_region_name
image = create_image_uri(region_name, TFSModel.FRAMEWORK_NAME, instance_type,
self._framework_version, 'py3')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is to change create image uri instead of reusing and striping it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of fussy behavior in create_image_uri. it would be easy to fall out of sync

with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
model = TFSModel(model_data, 'SageMakerRole', framework_version=tf_full_version)
predictor = model.deploy(1, 'ml.c5.xlarge', endpoint_name=endpoint_name)
yield predictor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test setup

serializer=sagemaker.predictor.csv_serializer)

result = predictor.predict(input_data)
assert expected_result == result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing test cases for errors and empty requests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • handled in unit tests and in container package tests
  • also this is generic predictor / serializer behavior that is well covered by other tests

@jesterhazy
jesterhazy merged commit b6c9b0c into aws:masterNov 7, 2018
@jesterhazy
jesterhazy deleted the je-tfs branch December 9, 2018 19:37
Evan-W-ang added a commit to Evan-W-ang/sagemaker-python-sdk that referenced this pull request Jun 8, 2026
* add tensorflow serving container support
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jesterhazy@codecov-io@mvsusp@owen-t
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

add tfs container support - #460

Merged
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs
Nov 7, 2018
Merged

add tfs container support#460
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs

Conversation

@jesterhazy

@jesterhazyjesterhazy commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

Description of changes:

add support for sagemaker-tfs inference container

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have updated the changelog with a description of my changes (if appropriate)
  • I have updated any necessary documentation (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-io

codecov-io commented Nov 6, 2018

Copy link
Copy Markdown

Codecov Report

Merging #460 into master will increase coverage by 0.08%.
The diff coverage is 97.95%.

Impacted file tree graph

@@ Coverage Diff @@## master #460 +/- ##
==========================================
+ Coverage 93.77% 93.86% +0.08% 
==========================================
Files 55 56 +1 Lines 4114 4190 +76 ==========================================
+ Hits 3858 3933 +75 - Misses 256 257 +1
Impacted FilesCoverage Δ
src/sagemaker/predictor.py96.77% <100%> (+0.17%)⬆️
src/sagemaker/tensorflow/estimator.py93.83% <95%> (+0.26%)⬆️
src/sagemaker/tensorflow/serving.py98.38% <98.38%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 868f81b...61dd059. Read the comment docs.

owen-t
owen-t previously approved these changes Nov 6, 2018

@owen-towen-t left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider including Readme updates as well.

Comment threadsrc/sagemaker/tensorflow/estimator.py
Comment threadsrc/sagemaker/predictor.py Outdated
If a serializer was specified when creating the RealTimePredictor, the result of the
serializer is sent as input data. Otherwise the data must be sequence of bytes, and
the predict method then sends the bytes in the request body as is.
initial_args (dict[str,str]): Optional. Initial request arguments. Default is None.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify more this docstring argument.

Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/tensorflow/__init__.py Outdated

from sagemaker.tensorflow.estimator import TensorFlow # noqa: E402, F401
from sagemaker.tensorflow.model import TensorFlowModel, TensorFlowPredictor # noqa: E402, F401
from sagemaker.tensorflow.tfs import TFSModel, TFSPredictor # noqa: E402, F401

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid acronyms to keep the same pattern of the SDK

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TensorFlowServingModel' is unwieldy, and ambiguous since TensorFlowModel also refers to a kind of TensorFlow Serving model. TFS is well aligned with the module name, and the container side package name.

Another option... just calling them Model and Predictor (sagemaker.tensorflow.tfs.Model etc), but this invites collision with sagemaker.Model etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about sagemaker.tesorflow.serving.Model or sagemaker.tensorflow_serving.Model?

Collision should not happen if we are importing modules not classes like specified in the style guide.

Comment threadCHANGELOG.rst Outdated
1.14.0-dev
==========

* add support for sagemaker-tfs container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow correct changelog format.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

name=self._current_job_name,
framework_version=self.framework_version,
sagemaker_session=self.sagemaker_session,
vpc_config=self.get_vpc_config(vpc_config_override))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing container_log_level?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

from sagemaker import Model, RealTimePredictor
from sagemaker.content_types import CONTENT_TYPE_JSON
from sagemaker.fw_utils import create_image_uri
from sagemaker.predictor import json_serializer, json_deserializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from google python style guide -> import modules not functions and classes.

attributes.append('tfs-model-name={}'.format(model_name))
if model_version:
attributes.append('tfs-model-version={}'.format(model_version))
self._model_attributes = ','.join(attributes) if attributes else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an empty array to represent an empty list of model attributes instead of None?

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated


class TFSModel(Model):
FRAMEWORK_NAME = 'tfs'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that other classes use dunders instead of a constant, although I Iike your style better and matches the conventions https://github.com/google/styleguide/blob/gh-pages/pyguide.md#3164-guidelines-derived-from-guidos-recommendations

nit: consider leaving it at module level

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dictionaries are not constants in Python.

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated
return self.env

env = dict(self.env)
env['SAGEMAKER_TFS_NGINX_LOGLEVEL'] = TFSModel.LOG_LEVEL_MAP[self._container_log_level]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a constant for this key.

# reuse standard image uri function, then strip unwanted python component
region_name = self.sagemaker_session.boto_region_name
image = create_image_uri(region_name, TFSModel.FRAMEWORK_NAME, instance_type,
self._framework_version, 'py3')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is to change create image uri instead of reusing and striping it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of fussy behavior in create_image_uri. it would be easy to fall out of sync

with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
model = TFSModel(model_data, 'SageMakerRole', framework_version=tf_full_version)
predictor = model.deploy(1, 'ml.c5.xlarge', endpoint_name=endpoint_name)
yield predictor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test setup

serializer=sagemaker.predictor.csv_serializer)

result = predictor.predict(input_data)
assert expected_result == result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing test cases for errors and empty requests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • handled in unit tests and in container package tests
  • also this is generic predictor / serializer behavior that is well covered by other tests

@jesterhazy
jesterhazy merged commit b6c9b0c into aws:masterNov 7, 2018
@jesterhazy
jesterhazy deleted the je-tfs branch December 9, 2018 19:37
Evan-W-ang added a commit to Evan-W-ang/sagemaker-python-sdk that referenced this pull request Jun 8, 2026
* add tensorflow serving container support
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jesterhazy@codecov-io@mvsusp@owen-t
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

add tfs container support - #460

Merged
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs
Nov 7, 2018
Merged

add tfs container support#460
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs

Conversation

@jesterhazy

@jesterhazyjesterhazy commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

Description of changes:

add support for sagemaker-tfs inference container

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have updated the changelog with a description of my changes (if appropriate)
  • I have updated any necessary documentation (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-io

codecov-io commented Nov 6, 2018

Copy link
Copy Markdown

Codecov Report

Merging #460 into master will increase coverage by 0.08%.
The diff coverage is 97.95%.

Impacted file tree graph

@@ Coverage Diff @@## master #460 +/- ##
==========================================
+ Coverage 93.77% 93.86% +0.08% 
==========================================
Files 55 56 +1 Lines 4114 4190 +76 ==========================================
+ Hits 3858 3933 +75 - Misses 256 257 +1
Impacted FilesCoverage Δ
src/sagemaker/predictor.py96.77% <100%> (+0.17%)⬆️
src/sagemaker/tensorflow/estimator.py93.83% <95%> (+0.26%)⬆️
src/sagemaker/tensorflow/serving.py98.38% <98.38%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 868f81b...61dd059. Read the comment docs.

owen-t
owen-t previously approved these changes Nov 6, 2018

@owen-towen-t left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider including Readme updates as well.

Comment threadsrc/sagemaker/tensorflow/estimator.py
Comment threadsrc/sagemaker/predictor.py Outdated
If a serializer was specified when creating the RealTimePredictor, the result of the
serializer is sent as input data. Otherwise the data must be sequence of bytes, and
the predict method then sends the bytes in the request body as is.
initial_args (dict[str,str]): Optional. Initial request arguments. Default is None.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify more this docstring argument.

Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/tensorflow/__init__.py Outdated

from sagemaker.tensorflow.estimator import TensorFlow # noqa: E402, F401
from sagemaker.tensorflow.model import TensorFlowModel, TensorFlowPredictor # noqa: E402, F401
from sagemaker.tensorflow.tfs import TFSModel, TFSPredictor # noqa: E402, F401

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid acronyms to keep the same pattern of the SDK

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TensorFlowServingModel' is unwieldy, and ambiguous since TensorFlowModel also refers to a kind of TensorFlow Serving model. TFS is well aligned with the module name, and the container side package name.

Another option... just calling them Model and Predictor (sagemaker.tensorflow.tfs.Model etc), but this invites collision with sagemaker.Model etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about sagemaker.tesorflow.serving.Model or sagemaker.tensorflow_serving.Model?

Collision should not happen if we are importing modules not classes like specified in the style guide.

Comment threadCHANGELOG.rst Outdated
1.14.0-dev
==========

* add support for sagemaker-tfs container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow correct changelog format.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

name=self._current_job_name,
framework_version=self.framework_version,
sagemaker_session=self.sagemaker_session,
vpc_config=self.get_vpc_config(vpc_config_override))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing container_log_level?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

from sagemaker import Model, RealTimePredictor
from sagemaker.content_types import CONTENT_TYPE_JSON
from sagemaker.fw_utils import create_image_uri
from sagemaker.predictor import json_serializer, json_deserializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from google python style guide -> import modules not functions and classes.

attributes.append('tfs-model-name={}'.format(model_name))
if model_version:
attributes.append('tfs-model-version={}'.format(model_version))
self._model_attributes = ','.join(attributes) if attributes else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an empty array to represent an empty list of model attributes instead of None?

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated


class TFSModel(Model):
FRAMEWORK_NAME = 'tfs'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that other classes use dunders instead of a constant, although I Iike your style better and matches the conventions https://github.com/google/styleguide/blob/gh-pages/pyguide.md#3164-guidelines-derived-from-guidos-recommendations

nit: consider leaving it at module level

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dictionaries are not constants in Python.

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated
return self.env

env = dict(self.env)
env['SAGEMAKER_TFS_NGINX_LOGLEVEL'] = TFSModel.LOG_LEVEL_MAP[self._container_log_level]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a constant for this key.

# reuse standard image uri function, then strip unwanted python component
region_name = self.sagemaker_session.boto_region_name
image = create_image_uri(region_name, TFSModel.FRAMEWORK_NAME, instance_type,
self._framework_version, 'py3')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is to change create image uri instead of reusing and striping it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of fussy behavior in create_image_uri. it would be easy to fall out of sync

with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
model = TFSModel(model_data, 'SageMakerRole', framework_version=tf_full_version)
predictor = model.deploy(1, 'ml.c5.xlarge', endpoint_name=endpoint_name)
yield predictor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test setup

serializer=sagemaker.predictor.csv_serializer)

result = predictor.predict(input_data)
assert expected_result == result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing test cases for errors and empty requests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • handled in unit tests and in container package tests
  • also this is generic predictor / serializer behavior that is well covered by other tests

@jesterhazy
jesterhazy merged commit b6c9b0c into aws:masterNov 7, 2018
@jesterhazy
jesterhazy deleted the je-tfs branch December 9, 2018 19:37
Evan-W-ang added a commit to Evan-W-ang/sagemaker-python-sdk that referenced this pull request Jun 8, 2026
* add tensorflow serving container support
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jesterhazy@codecov-io@mvsusp@owen-t
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

add tfs container support - #460

Merged
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs
Nov 7, 2018
Merged

add tfs container support#460
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs

Conversation

@jesterhazy

@jesterhazyjesterhazy commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

Description of changes:

add support for sagemaker-tfs inference container

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have updated the changelog with a description of my changes (if appropriate)
  • I have updated any necessary documentation (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-io

codecov-io commented Nov 6, 2018

Copy link
Copy Markdown

Codecov Report

Merging #460 into master will increase coverage by 0.08%.
The diff coverage is 97.95%.

Impacted file tree graph

@@ Coverage Diff @@## master #460 +/- ##
==========================================
+ Coverage 93.77% 93.86% +0.08% 
==========================================
Files 55 56 +1 Lines 4114 4190 +76 ==========================================
+ Hits 3858 3933 +75 - Misses 256 257 +1
Impacted FilesCoverage Δ
src/sagemaker/predictor.py96.77% <100%> (+0.17%)⬆️
src/sagemaker/tensorflow/estimator.py93.83% <95%> (+0.26%)⬆️
src/sagemaker/tensorflow/serving.py98.38% <98.38%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 868f81b...61dd059. Read the comment docs.

owen-t
owen-t previously approved these changes Nov 6, 2018

@owen-towen-t left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider including Readme updates as well.

Comment threadsrc/sagemaker/tensorflow/estimator.py
Comment threadsrc/sagemaker/predictor.py Outdated
If a serializer was specified when creating the RealTimePredictor, the result of the
serializer is sent as input data. Otherwise the data must be sequence of bytes, and
the predict method then sends the bytes in the request body as is.
initial_args (dict[str,str]): Optional. Initial request arguments. Default is None.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify more this docstring argument.

Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/tensorflow/__init__.py Outdated

from sagemaker.tensorflow.estimator import TensorFlow # noqa: E402, F401
from sagemaker.tensorflow.model import TensorFlowModel, TensorFlowPredictor # noqa: E402, F401
from sagemaker.tensorflow.tfs import TFSModel, TFSPredictor # noqa: E402, F401

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid acronyms to keep the same pattern of the SDK

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TensorFlowServingModel' is unwieldy, and ambiguous since TensorFlowModel also refers to a kind of TensorFlow Serving model. TFS is well aligned with the module name, and the container side package name.

Another option... just calling them Model and Predictor (sagemaker.tensorflow.tfs.Model etc), but this invites collision with sagemaker.Model etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about sagemaker.tesorflow.serving.Model or sagemaker.tensorflow_serving.Model?

Collision should not happen if we are importing modules not classes like specified in the style guide.

Comment threadCHANGELOG.rst Outdated
1.14.0-dev
==========

* add support for sagemaker-tfs container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow correct changelog format.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

name=self._current_job_name,
framework_version=self.framework_version,
sagemaker_session=self.sagemaker_session,
vpc_config=self.get_vpc_config(vpc_config_override))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing container_log_level?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

from sagemaker import Model, RealTimePredictor
from sagemaker.content_types import CONTENT_TYPE_JSON
from sagemaker.fw_utils import create_image_uri
from sagemaker.predictor import json_serializer, json_deserializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from google python style guide -> import modules not functions and classes.

attributes.append('tfs-model-name={}'.format(model_name))
if model_version:
attributes.append('tfs-model-version={}'.format(model_version))
self._model_attributes = ','.join(attributes) if attributes else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an empty array to represent an empty list of model attributes instead of None?

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated


class TFSModel(Model):
FRAMEWORK_NAME = 'tfs'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that other classes use dunders instead of a constant, although I Iike your style better and matches the conventions https://github.com/google/styleguide/blob/gh-pages/pyguide.md#3164-guidelines-derived-from-guidos-recommendations

nit: consider leaving it at module level

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dictionaries are not constants in Python.

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated
return self.env

env = dict(self.env)
env['SAGEMAKER_TFS_NGINX_LOGLEVEL'] = TFSModel.LOG_LEVEL_MAP[self._container_log_level]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a constant for this key.

# reuse standard image uri function, then strip unwanted python component
region_name = self.sagemaker_session.boto_region_name
image = create_image_uri(region_name, TFSModel.FRAMEWORK_NAME, instance_type,
self._framework_version, 'py3')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is to change create image uri instead of reusing and striping it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of fussy behavior in create_image_uri. it would be easy to fall out of sync

with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
model = TFSModel(model_data, 'SageMakerRole', framework_version=tf_full_version)
predictor = model.deploy(1, 'ml.c5.xlarge', endpoint_name=endpoint_name)
yield predictor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test setup

serializer=sagemaker.predictor.csv_serializer)

result = predictor.predict(input_data)
assert expected_result == result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing test cases for errors and empty requests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • handled in unit tests and in container package tests
  • also this is generic predictor / serializer behavior that is well covered by other tests

@jesterhazy
jesterhazy merged commit b6c9b0c into aws:masterNov 7, 2018
@jesterhazy
jesterhazy deleted the je-tfs branch December 9, 2018 19:37
Evan-W-ang added a commit to Evan-W-ang/sagemaker-python-sdk that referenced this pull request Jun 8, 2026
* add tensorflow serving container support
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jesterhazy@codecov-io@mvsusp@owen-t
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

add tfs container support - #460

Merged
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs
Nov 7, 2018
Merged

add tfs container support#460
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs

Conversation

@jesterhazy

@jesterhazyjesterhazy commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

Description of changes:

add support for sagemaker-tfs inference container

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have updated the changelog with a description of my changes (if appropriate)
  • I have updated any necessary documentation (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-io

codecov-io commented Nov 6, 2018

Copy link
Copy Markdown

Codecov Report

Merging #460 into master will increase coverage by 0.08%.
The diff coverage is 97.95%.

Impacted file tree graph

@@ Coverage Diff @@## master #460 +/- ##
==========================================
+ Coverage 93.77% 93.86% +0.08% 
==========================================
Files 55 56 +1 Lines 4114 4190 +76 ==========================================
+ Hits 3858 3933 +75 - Misses 256 257 +1
Impacted FilesCoverage Δ
src/sagemaker/predictor.py96.77% <100%> (+0.17%)⬆️
src/sagemaker/tensorflow/estimator.py93.83% <95%> (+0.26%)⬆️
src/sagemaker/tensorflow/serving.py98.38% <98.38%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 868f81b...61dd059. Read the comment docs.

owen-t
owen-t previously approved these changes Nov 6, 2018

@owen-towen-t left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider including Readme updates as well.

Comment threadsrc/sagemaker/tensorflow/estimator.py
Comment threadsrc/sagemaker/predictor.py Outdated
If a serializer was specified when creating the RealTimePredictor, the result of the
serializer is sent as input data. Otherwise the data must be sequence of bytes, and
the predict method then sends the bytes in the request body as is.
initial_args (dict[str,str]): Optional. Initial request arguments. Default is None.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify more this docstring argument.

Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/tensorflow/__init__.py Outdated

from sagemaker.tensorflow.estimator import TensorFlow # noqa: E402, F401
from sagemaker.tensorflow.model import TensorFlowModel, TensorFlowPredictor # noqa: E402, F401
from sagemaker.tensorflow.tfs import TFSModel, TFSPredictor # noqa: E402, F401

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid acronyms to keep the same pattern of the SDK

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TensorFlowServingModel' is unwieldy, and ambiguous since TensorFlowModel also refers to a kind of TensorFlow Serving model. TFS is well aligned with the module name, and the container side package name.

Another option... just calling them Model and Predictor (sagemaker.tensorflow.tfs.Model etc), but this invites collision with sagemaker.Model etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about sagemaker.tesorflow.serving.Model or sagemaker.tensorflow_serving.Model?

Collision should not happen if we are importing modules not classes like specified in the style guide.

Comment threadCHANGELOG.rst Outdated
1.14.0-dev
==========

* add support for sagemaker-tfs container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow correct changelog format.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

name=self._current_job_name,
framework_version=self.framework_version,
sagemaker_session=self.sagemaker_session,
vpc_config=self.get_vpc_config(vpc_config_override))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing container_log_level?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

from sagemaker import Model, RealTimePredictor
from sagemaker.content_types import CONTENT_TYPE_JSON
from sagemaker.fw_utils import create_image_uri
from sagemaker.predictor import json_serializer, json_deserializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from google python style guide -> import modules not functions and classes.

attributes.append('tfs-model-name={}'.format(model_name))
if model_version:
attributes.append('tfs-model-version={}'.format(model_version))
self._model_attributes = ','.join(attributes) if attributes else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an empty array to represent an empty list of model attributes instead of None?

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated


class TFSModel(Model):
FRAMEWORK_NAME = 'tfs'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that other classes use dunders instead of a constant, although I Iike your style better and matches the conventions https://github.com/google/styleguide/blob/gh-pages/pyguide.md#3164-guidelines-derived-from-guidos-recommendations

nit: consider leaving it at module level

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dictionaries are not constants in Python.

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated
return self.env

env = dict(self.env)
env['SAGEMAKER_TFS_NGINX_LOGLEVEL'] = TFSModel.LOG_LEVEL_MAP[self._container_log_level]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a constant for this key.

# reuse standard image uri function, then strip unwanted python component
region_name = self.sagemaker_session.boto_region_name
image = create_image_uri(region_name, TFSModel.FRAMEWORK_NAME, instance_type,
self._framework_version, 'py3')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is to change create image uri instead of reusing and striping it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of fussy behavior in create_image_uri. it would be easy to fall out of sync

with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
model = TFSModel(model_data, 'SageMakerRole', framework_version=tf_full_version)
predictor = model.deploy(1, 'ml.c5.xlarge', endpoint_name=endpoint_name)
yield predictor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test setup

serializer=sagemaker.predictor.csv_serializer)

result = predictor.predict(input_data)
assert expected_result == result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing test cases for errors and empty requests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • handled in unit tests and in container package tests
  • also this is generic predictor / serializer behavior that is well covered by other tests

@jesterhazy
jesterhazy merged commit b6c9b0c into aws:masterNov 7, 2018
@jesterhazy
jesterhazy deleted the je-tfs branch December 9, 2018 19:37
Evan-W-ang added a commit to Evan-W-ang/sagemaker-python-sdk that referenced this pull request Jun 8, 2026
* add tensorflow serving container support
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jesterhazy@codecov-io@mvsusp@owen-t
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

add tfs container support - #460

Merged
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs
Nov 7, 2018
Merged

add tfs container support#460
jesterhazy merged 8 commits into
aws:masterfrom
jesterhazy:je-tfs

Conversation

@jesterhazy

@jesterhazyjesterhazy commented Nov 6, 2018

Copy link
Copy Markdown
Contributor

Description of changes:

add support for sagemaker-tfs inference container

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have updated the changelog with a description of my changes (if appropriate)
  • I have updated any necessary documentation (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-io

codecov-io commented Nov 6, 2018

Copy link
Copy Markdown

Codecov Report

Merging #460 into master will increase coverage by 0.08%.
The diff coverage is 97.95%.

Impacted file tree graph

@@ Coverage Diff @@## master #460 +/- ##
==========================================
+ Coverage 93.77% 93.86% +0.08% 
==========================================
Files 55 56 +1 Lines 4114 4190 +76 ==========================================
+ Hits 3858 3933 +75 - Misses 256 257 +1
Impacted FilesCoverage Δ
src/sagemaker/predictor.py96.77% <100%> (+0.17%)⬆️
src/sagemaker/tensorflow/estimator.py93.83% <95%> (+0.26%)⬆️
src/sagemaker/tensorflow/serving.py98.38% <98.38%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 868f81b...61dd059. Read the comment docs.

owen-t
owen-t previously approved these changes Nov 6, 2018

@owen-towen-t left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider including Readme updates as well.

Comment threadsrc/sagemaker/tensorflow/estimator.py
Comment threadsrc/sagemaker/predictor.py Outdated
If a serializer was specified when creating the RealTimePredictor, the result of the
serializer is sent as input data. Otherwise the data must be sequence of bytes, and
the predict method then sends the bytes in the request body as is.
initial_args (dict[str,str]): Optional. Initial request arguments. Default is None.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify more this docstring argument.

Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/predictor.py
Comment threadsrc/sagemaker/tensorflow/__init__.py Outdated

from sagemaker.tensorflow.estimator import TensorFlow # noqa: E402, F401
from sagemaker.tensorflow.model import TensorFlowModel, TensorFlowPredictor # noqa: E402, F401
from sagemaker.tensorflow.tfs import TFSModel, TFSPredictor # noqa: E402, F401

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid acronyms to keep the same pattern of the SDK

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TensorFlowServingModel' is unwieldy, and ambiguous since TensorFlowModel also refers to a kind of TensorFlow Serving model. TFS is well aligned with the module name, and the container side package name.

Another option... just calling them Model and Predictor (sagemaker.tensorflow.tfs.Model etc), but this invites collision with sagemaker.Model etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about sagemaker.tesorflow.serving.Model or sagemaker.tensorflow_serving.Model?

Collision should not happen if we are importing modules not classes like specified in the style guide.

Comment threadCHANGELOG.rst Outdated
1.14.0-dev
==========

* add support for sagemaker-tfs container

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow correct changelog format.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

name=self._current_job_name,
framework_version=self.framework_version,
sagemaker_session=self.sagemaker_session,
vpc_config=self.get_vpc_config(vpc_config_override))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing container_log_level?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

from sagemaker import Model, RealTimePredictor
from sagemaker.content_types import CONTENT_TYPE_JSON
from sagemaker.fw_utils import create_image_uri
from sagemaker.predictor import json_serializer, json_deserializer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from google python style guide -> import modules not functions and classes.

attributes.append('tfs-model-name={}'.format(model_name))
if model_version:
attributes.append('tfs-model-version={}'.format(model_version))
self._model_attributes = ','.join(attributes) if attributes else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use an empty array to represent an empty list of model attributes instead of None?

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated


class TFSModel(Model):
FRAMEWORK_NAME = 'tfs'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that other classes use dunders instead of a constant, although I Iike your style better and matches the conventions https://github.com/google/styleguide/blob/gh-pages/pyguide.md#3164-guidelines-derived-from-guidos-recommendations

nit: consider leaving it at module level

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

logging.WARNING: 'warn',
logging.ERROR: 'error',
logging.CRITICAL: 'crit',
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dictionaries are not constants in Python.

Comment threadsrc/sagemaker/tensorflow/tfs.py Outdated
return self.env

env = dict(self.env)
env['SAGEMAKER_TFS_NGINX_LOGLEVEL'] = TFSModel.LOG_LEVEL_MAP[self._container_log_level]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a constant for this key.

# reuse standard image uri function, then strip unwanted python component
region_name = self.sagemaker_session.boto_region_name
image = create_image_uri(region_name, TFSModel.FRAMEWORK_NAME, instance_type,
self._framework_version, 'py3')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard is to change create image uri instead of reusing and striping it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of fussy behavior in create_image_uri. it would be easy to fall out of sync

with timeout_and_delete_endpoint_by_name(endpoint_name, sagemaker_session):
model = TFSModel(model_data, 'SageMakerRole', framework_version=tf_full_version)
predictor = model.deploy(1, 'ml.c5.xlarge', endpoint_name=endpoint_name)
yield predictor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test setup

serializer=sagemaker.predictor.csv_serializer)

result = predictor.predict(input_data)
assert expected_result == result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are missing test cases for errors and empty requests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • handled in unit tests and in container package tests
  • also this is generic predictor / serializer behavior that is well covered by other tests

@jesterhazy
jesterhazy merged commit b6c9b0c into aws:masterNov 7, 2018
@jesterhazy
jesterhazy deleted the je-tfs branch December 9, 2018 19:37
Evan-W-ang added a commit to Evan-W-ang/sagemaker-python-sdk that referenced this pull request Jun 8, 2026
* add tensorflow serving container support
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jesterhazy@codecov-io@mvsusp@owen-t