Skip to content

Draft: Java API to use tf.function available on SavedModel. #89

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

Merged
merged 1 commit into from
Jul 28, 2020

Conversation

Shajan
Copy link
Contributor

@Shajan Shajan commented Jul 27, 2020

Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

TBD: Unit tests before this change is ready to merge.

Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function
@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

Shajan referenced this pull request Jul 27, 2020
Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function
@karllessard
Copy link
Collaborator

karllessard commented Jul 27, 2020

Hi @Shajan , can you please rebase this PR to merge it in the shared branch created for this story we will working on together instead of master? https://github.com/tensorflow/java/tree/shared-saved-model

I think we should merge it back to master only when the whole solution is complete

@Shajan Shajan changed the base branch from master to shared-saved-model July 27, 2020 23:41
@Shajan
Copy link
Contributor Author

Shajan commented Jul 27, 2020

@karllessard i tried to rebase and then push the change to tensorflow:shared-saved-model i may not have permission to do so. Instead i made a pull request to the shared-saved-model branch.

@karllessard karllessard merged commit d845856 into tensorflow:shared-saved-model Jul 28, 2020
@karllessard
Copy link
Collaborator

Thanks @Shajan , it's ok I've merged it and sent you an invite to collaborate to this repository, I think after you accept it, I will be able to give you write access to the shared branch

@Shajan
Copy link
Contributor Author

Shajan commented Jul 28, 2020

Thanks @karllessard got the invite. Will wait for you to merge your changes and then add tests.

@Shajan Shajan deleted the sd/tf.function branch July 28, 2020 16:29
* input / output parameters of a <a
* href="https://www.tensorflow.org/api_docs/python/tf/function">tf.function</a>
*/
public static final class SignatureToNodeName {
Copy link

@yzhuang yzhuang Jul 30, 2020

Choose a reason for hiding this comment

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

Read through this change, and I believe the following API design would be both cleaner and more intuitive to use. Wdyt?

  1. Update Loader and add withSignature(String... signatures).
  2. Update Loader.load() to also construct TfFunctions corresponding to the specified signatures.
  3. SignatureToNodeName can become private and not exposed to end user, preferrably living inside TfFunction as private.
  4. TfFunction should not have a reference to the session. Let SavedModelBundle manage the session (which it already does). TfFunction can become a pure data class.
  5. Add SavedModelBundle.call(String signature, Map<String, Tensor<?>> inputs, Map<String, Tensor<?>> outputs) to SavedModelBundle. TfFunction can become private and not exposed to end user as well.

What do you think about the above proposed API design?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not exposing SignatureToNodeName (3) sounds good
TtFunction not having reference to session (4) is good as well

Regarding (5), it is desirable to have a way to do repeated call to the same function. Having a TfFuction class allows for this. I am also thinking removing runtime check currently done with each call in the Tensor call(Tensor) method and do that once.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for your proposal @yzhuang , some thoughts on it:

SignatureToNodeName can become private and not exposed to end user, preferrably living inside TfFunction as private.

Looking at it, getSignatureToNodeName() can already be private in SavedModelBundle and SignatureToNodeName could be restricted at the default-package level. I don't think it should be in TfFunction though as it maps all signatures while an instance of TfFunction is only mapped to one of them.

TfFunction should not have a reference to the session. Let SavedModelBundle manage the session (which it already does). TfFunction can become a pure data class.

That would prevent though to just invoke function.call(tensor) to run the graph, which I personally like. While I understand that data classes have their lot of advantages, I'm not sure there is real gains for having TfFunction as one of them, especially that Session instances are thread-safe.

Add SavedModelBundle.call(String signature, Map<String, Tensor> inputs, Map> outputs) to SavedModelBundle. TfFunction can become private and not exposed to end user as well.

Again, I personally like the OO approach of letting users manipulating callable entities instead of having SavedModelBundle acting as a "service". Is the intention here is just to hide the TfFunction at the user level? Note that I was planning to reuse the same object to add new signatures to a model when exporting it (but I could also do it just with SavedModelBundle if we decide to take that direction).

Copy link

Choose a reason for hiding this comment

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

Hi Karl and Shajan,

I have been busy with traveling, and didn't have time to follow up on this thread. Please feel free to take whatever you find helpful from my suggestions, and discard the rest. Thank you for taking time to go through my comments!

Copy link

@yzhuang yzhuang Aug 16, 2020

Choose a reason for hiding this comment

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

Hi @karllessard and @Shajan ,

Sorry for the late reply on your comment—just landed in Hong Kong :)

My suggestion to let SavedModel manage the session is not about thread safety, but about resource ownership. SavedModel currently “owns” the session and is responsible for closing the resource to avoid memory leaks. If we create TFFunction objects holding references to the session, it complicate the resource ownership mental model. For example, we will need to do things such as the below:

  1. Perform reference counting on the session, and have the last “user” of the session close it. This is user friendly, but introduces complexity and room for bugs. OR
  2. Continue to let SavedModel own the session, but TFFunction objects need to anticipate that it’s underlying resource (the session) can become defunct at anytime. This can be counterintuitive to users as users likely need to surround their call with a try/catch.

Is the intention here is just to hide the TfFunction at the user level?

My intention was to not have to think about the resource ownership problem, and keep the resource ownership unchanged. The API of having TFFunctions be callable and exposed to users sounds great to me, and we need to think about the above 1 & 2 though. This is not a contrived scenario: we already do model hot swapping at Twitter in our prediction servers, and SavedModels are hot swapped without restarting the JVM.

Thank you Karl and Shajan!

@karllessard
Copy link
Collaborator

@yzhuang , this SIG is having a community video chat where we will discuss about this topic, among other things. Are you available and interested to join?

@Shajan
Copy link
Contributor Author

Shajan commented Aug 14, 2020

@karllessard missed the meeting today. I see the decision to be

Confirmation: lets model the API with functions while still loading/saving session-centric graphs

I take it that we go with the current branch (after addressing open comments) and adding unit tests.

For unit tests: Here is a proposal

  • Checkin savedmodel (created using python) as a resource
  • [optionally] Add the python model + instructions (but not have the test run python code)

karllessard pushed a commit that referenced this pull request Aug 24, 2020
Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>
karllessard pushed a commit to karllessard/tensorflow-java that referenced this pull request Aug 24, 2020
…ow#89)

Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>
karllessard added a commit that referenced this pull request Aug 28, 2020
* Draft: Java API to use tf.function available on SavedModel. (#89)

Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>

* Change API for creating concrete functions and exporting them to a saved model

Co-authored-by: Karl Lessard <[email protected]>
karllessard pushed a commit that referenced this pull request Sep 11, 2020
Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>

Save models as functions (#103)

* Draft: Java API to use tf.function available on SavedModel. (#89)

Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>

* Change API for creating concrete functions and exporting them to a saved model

Co-authored-by: Karl Lessard <[email protected]>

Rename signature name to key

Print function signature when converting to String

Add method that returns the signature of all functions in a saved model

Add unit tests for python created SavedModel with tf.function
karllessard pushed a commit that referenced this pull request Sep 16, 2020
Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>

Save models as functions (#103)

* Draft: Java API to use tf.function available on SavedModel. (#89)

Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>

* Change API for creating concrete functions and exporting them to a saved model

Co-authored-by: Karl Lessard <[email protected]>

Rename signature name to key

Print function signature when converting to String

Add method that returns the signature of all functions in a saved model

Add unit tests for python created SavedModel with tf.function
Craigacp pushed a commit that referenced this pull request Sep 17, 2020
* Create, save and load models using functional API

Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>

Save models as functions (#103)

* Draft: Java API to use tf.function available on SavedModel. (#89)

Python models that contain tf.function is inconvenient to be consumed by Java clients.
This proposal provides an API to
(a) Invoke a tf.function, given the signature name
(b) Retrieve the node name in the graph corresponding to a tf.function

Co-authored-by: Shajan Dasan <[email protected]>

* Change API for creating concrete functions and exporting them to a saved model

Co-authored-by: Karl Lessard <[email protected]>

Rename signature name to key

Print function signature when converting to String

Add method that returns the signature of all functions in a saved model

Add unit tests for python created SavedModel with tf.function

* Add validations on signatures and saved models

* Convert text file to Python

* Add copyright on Python sample

Co-authored-by: Shajan Dasan <[email protected]>
Sign up for free to 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.

5 participants