Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add inference error messages in WIT notebook mode #2414

Merged
merged 5 commits into from
Jul 15, 2019

Conversation

jameswex
Copy link
Contributor

@jameswex jameswex commented Jul 8, 2019

  • Motivation for features / changes

If a model fails to run inference in WitWidget, no error is currently displayed so the user has no idea why WIT isn't working correctly. This change adds in proper error handling.

  • Technical description of changes

Updated jupyter and colab witwidget code so that if inference throws any python error, it is properly caught and sent to the frontend.
The frontend now displays that inference error in a toast and in the status message.
Also fixed a small bug where when comparing 2 regression models, the initial Facets Dive view doesn't compare the two models.

  • Screenshots of UI changes

errorwit

  • Detailed steps to verify changes work correctly (as executed by you)

Ran colab and jupyter notebooks with and without inference errors to see that the error message in both cases gets to the user.
Ran a two-model regression notebook to see proper default Dive display.

@jameswex
Copy link
Contributor Author

jameswex commented Jul 8, 2019

@tolga-b please review

@jameswex jameswex requested a review from stephanwlee July 9, 2019 15:16
@jameswex
Copy link
Contributor Author

jameswex commented Jul 9, 2019

@stephanwlee please review, thanks

handleError_: function(errorStr) {
this.showToast_(errorStr);
this.exampleStatusStr = errorStr;
this.$.spinner.hidden = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please use the Polymer data binding instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

this.exampleStatusStr = 'Request failed';
this.showToast_('Request failed: ' + reason);
this.$.spinner.hidden = true;
this.handleError_('Request failed: ' + reason);
Copy link
Contributor

Choose a reason for hiding this comment

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

Strings like 'Request failed' often don't mean anything to the user (especially if it is a toast; which request? TensorBoard's request?). Please be a little bit more descriptive.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point. Adding new string param for what the request does, so that if it fails the error states what request failed (such as 'Datapoint load', or 'Model inference').

output.eval_js("""inferenceCallback('{inferences}')""".format(
inferences=json.dumps(inferences)))
except Exception as e:
error_str = str(e)
Copy link
Contributor

Choose a reason for hiding this comment

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

How is this used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thx, removed

@@ -90,6 +90,9 @@ def infer_mutants(wit_id, details):

// Javascript callbacks called by python code to communicate with WIT
// Polymer element.
window.backendError = errorStr => {{
wit.handleError_(errorStr);
Copy link
Contributor

Choose a reason for hiding this comment

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

make handleError_ a public method

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

inferences=json.dumps(inferences)))
try:
inferences = base.WitWidgetBase.infer_impl(self)
output.eval_js("""inferenceCallback('{inferences}')""".format(
Copy link
Contributor

Choose a reason for hiding this comment

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

Pardon the drive-by, but this is an injection vector when any of the
keys or values (recursively) of inferences contains a single quote:

>>> import json
>>> inferences = {"label_vocab": "',alert('hmm'),null[0],'"}
>>> js = """inferenceCallback('{inferences}')""".format(
...     inferences=json.dumps(inferences))
>>> print(js)
inferenceCallback('{"label_vocab": "',alert('hmm'),null[0],'"}')

I’d expect to see simply inferenceCallback({inferences}), without the
quotes, such that the JS gets an object literal rather than a string
literal. If it really needs to be a string for some reason, you can
create the string literal safely by JSON-encoding again (in either
Python or JS).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

replaced with object and not string.

inferences=json.dumps(inferences)))
except Exception as e:
error_str = str(e)
output.eval_js("""backendError('{error}')""".format(
Copy link
Contributor

@wchargin wchargin Jul 9, 2019

Choose a reason for hiding this comment

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

Likewise an injection vector, and this one may be plausibly hit even in
a non-malicious case, because Python exception texts frequently contain
single quotes:

>>> import json
>>> try: None.wat
... except Exception as e:
...   js = """backendError('{error}')""".format(error=json.dumps(str(e)))
...   print(js)
... 
backendError('"'NoneType' object has no attribute 'wat'"')
>>> # ^ JS syntax error

(More occurrences below.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

replaced with object and not string.

@jameswex
Copy link
Contributor Author

addressed @stephanwlee and @wchargin comments

@stephanwlee stephanwlee self-requested a review July 12, 2019 14:55
Copy link
Contributor

@stephanwlee stephanwlee left a comment

Choose a reason for hiding this comment

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

All comments are nits.

makeAsyncRequest_: function(
url, thenDoFn, postData, errorFn = () => {}) {
url, thenDoFn, postData, requestStr, errorFn = () => {}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

super nit: requestStr -> humanReadableRequestName?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

this.exampleStatusStr = 'Request failed';
this.showToast_('Request failed: ' + reason);
this.$.spinner.hidden = true;
this.handleError(requestStr + ' failed: ' + reason);
Copy link
Contributor

Choose a reason for hiding this comment

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

`Request for ${humanReadableRequestName} failed: ${reason}`

I thought it would be confusing to show a toast that says something like Model inference failed: foobarbaz

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

try:
inferences = base.WitWidgetBase.infer_impl(self)
output.eval_js("""inferenceCallback({inferences})""".format(
inferences=json.dumps(inferences)))
Copy link
Contributor

Choose a reason for hiding this comment

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

as per http://google.github.io/styleguide/pyguide.html#3192-line-breaking, you might want +2 more whitespace here and below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@wchargin wchargin dismissed their stale review July 12, 2019 16:50

Requests addressed; thank you!

@jameswex
Copy link
Contributor Author

@stephanwlee addressed your comments, thanks

@jameswex jameswex merged commit 839ceac into tensorflow:master Jul 15, 2019
@jameswex jameswex deleted the wit_display_error branch July 15, 2019 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants