-
Notifications
You must be signed in to change notification settings - Fork 201
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
Kotlin API #165
base: master
Are you sure you want to change the base?
Kotlin API #165
Conversation
Maven makes it really hard to hack something for native libraries like that, but if you do it exactly like in |
Unfortunate, but thanks for saving me the trouble of finding that out myself. Doesn't |
Yes, we're not copying all of tensorflow-core/pom.xml there... If you need to add/modify some profiles, it's probably a better idea to modify them there, or is there something preventing you from doing that? |
Yeah, I'll just depend on the api layer like |
@rnett It looks awesome, you add a few brilliant things like contract and with() usage and the proposed example with Dense layer look cool! But I keep in mind that in future we should add changes in Java and Kotlin ops both for each enough big PR for consistency, and I propose a solution here:
What do you think, @karllessard, it's a good topic for discussion and you drive API changes now |
In theory, and practice as far as I've seen (i.e. adding the ones op), any Ops added to the Java API will be automatically generated. I don't see any reason you would add an Op to the Kotlin API, I'm not even sure if it would work. We may want to add something to ensure that the kotlin generation is run when tensorflow-core is compiled, but I'm not familiar enough with Maven to know if that's possible or how to do it. Moving Other API changes may cause issues, but only for ones with Kotlin apis built on top of them. Currently this is only Graph and EagerExecutionEnviroment (and Session, but that's a proof of concept more than an actual API), and I think they are pretty stable (and the APIs are just DSL methods). Remember, too, that you can always just use the Java API from Kotlin. It may not be idiomatic, but it will work. While there will be more in the future, I definitely want to limit Kotlin APIs to extensions as much as possible, new classes like in the Session API should be avoided. Any changes to the Java API would have to be pretty significant to cause issues, and deleting the old Kotlin APIs is always a valid strategy if whoever is changing the Java API doesn't want to write new Kotlin ones. I definitely plan on waiting for the type system refactor. I'd like to generate the inline methods using DataType, I think it will be possible. There's a few more Java api changes I'd like to make and incorporate, like Session and indexing. Other than that, if there are any big fundamental API changes planned (type refactor scale), I agree it would be a good idea to wait on this until they are done. I don't think we need to wait for multiple receivers, as it's not coming until March (and even that's a prototype) and it would be a purely additive change. In the mean time I could define them in an interface and have I am going to add some tests. There shouldn't be any issues, since it's codegen that calls the Java method directly, but I do want to add a few manual tests just to ensure that. |
Also, while I think there's too many to change at this point, |
All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the ℹ️ Googlers: Go here for more info. |
1 similar comment
All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the ℹ️ Googlers: Go here for more info. |
@karllessard @Craigacp @zaleslaw (and anyone else w/ comments) This is ready for review. NonNull annotations will come in another PR, although I don't love how much they clutter up the Java code, so there may be some compromise on that. Tests are currently failing because of #248. |
After todays call: move to a Also, make the NdArray classes like Shape Kotlin-friendly (i.e. rename size to get) rather than adding extensions. |
Ok, I've split the artifacts into |
NDArray parts have been moved to tensorflow/java-ndarray#1, which should be merged first. |
The more I play with |
Keep in mind that it would be great if the solution for the Kotlin ops could also apply to the framework ops. |
I'm not sure it would, since afaik framework ops is adding more ops, while the Kotlin ops need to override the Java ones. But I'll look. |
There doesn't look to be a good solution. I'd use extensions, but importing them does not work well (see KTIJ-18859). If I get a quick response to that issue it might be feasible to just wait for a fix. In the mean time, the best I came up with is: public object KotlinExt {
public fun <T : TType> Ops.gather(
params: Operand<T>,
indices: Operand<out TNumber>,
axis: Operand<out TNumber>,
batchDims: Long? = null
): Gather<T> = gather<T>(
params,
indices,
axis,
*listOfNotNull(
batchDims?.let { org.tensorflow.op.core.Gather.batchDims(it) }
).toTypedArray()
)
} which lets you do something like: private fun Ops.testActivation(x: Operand<TFloat32>): Operand<TFloat32> {
with(KotlinExt) {
gather(x, x, x, batchDims = 4)
return nn.relu(x)
}
} with full autocomplete and type hints (and the extension functions are importable w/o the object). With some helper functions it's not bad, and decorators would help significantly. Thoughts @karllessard @zaleslaw? |
So in light of the context receivers proposal, I'm thinking of something like this in public interface WithOps{
public Ops getTf();
public default WithOps withSubScope(String name) ...
}
public final class Ops implements WithOps {
@Override
public Ops getTf(){
return this;
}
} This allows Kotlin code to use |
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
…it already Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
Signed-off-by: Ryan Nett <[email protected]>
This is the WIP pull request for the Kotlin API, as discussed here. Feedback is welcome.
Adding nullability annotations to the Java API will be done in a separate PR.
The Session API is a prototype, I plan on proposing some changes to the Java api (mostly having
run
return a Map-like class) that would make it doable as extensions rather than new classes.I plan on experimenting with adding platform artifacts to
tensorflow-core-kotlin
, which is why there's a bunch of currently unused javacpp stuff in the pom (they would just depend on their java counterparts).There's an example of a basic MNIST network in
src/test/kotlin/org/tensorflow/Example.kt
. I can't run it due tojnitensorflow in java.library.path
errors, so I have no idea if it works, but it shows off the API.I'm using explicit API mode and have enabled contracts since there's a lot of DSL-style methods that benefit from it.
I'm using ktlint for formatting with a 120 character line limit. It currently only checks format on compilation (instead of auto-formatting), I could go either way on this.