tensorflow / tensorflow

An Open Source Machine Learning Framework for Everyone
https://tensorflow.org
Apache License 2.0
185.65k stars 74.18k forks source link

Full-fledged Java api roadmap? #17390

Closed up-to-you closed 6 years ago

up-to-you commented 6 years ago

Are there any estimated plans for Java api development in terms of functionality ? The only absolute choice for Java language nowadays is Deeplearning4j, any plans to occupy a niche for Java language? By the term "full-fledged" I mean: constructing a graph from scratch (including most common math function/operations, respectively), train CNN, test CNN, recognize the result, all of this using Java language only. #14094 and #16120 is still in work and latter frozen for a few days. Just want to know your vision of future.

P.s. need to choose right framework for starting a project at the end of June.

angerson commented 6 years ago

@asimshankar Can you comment on this?

up-to-you commented 6 years ago

any news ?

Nicholas-Schaub commented 6 years ago

If we parse the protocol buffer byte array from TensorFlow.opList(), will this give us a full readout of the functions we can pass to Graph.opBuilder? My thought is just to get a list of all available functions with inputs and outputs from opList, then use these to parse valid/invalid values when try to build a graph. Based on how a pre-trained graph is loaded using this Java api, it seems like this approach should work for building a graph from scratch.

I am in the same boat as you @up-to-you, and after looking through DL4J I think my preference is to stick with Tensorflow.

up-to-you commented 6 years ago

@Nicholas-Schaub, thanks a lot, i will test this approach. Nice to have fellow in misfortune :) I hope the guys from Tensorflow will not let our boat drown in the pythonish quagmire :(

UPDATE

TensorFlow.registeredOpList() eventually delivers some operations description, but this is a painfull pain of it's translation to opBuilder , first of all, taking into account Java API is not covered by the TensorFlow API stability guarantees.

I do not have the goal of pushing this problem to Tensorflow developers, i just need information - will their automation tool for Java ops generation be ready soon or not ?

Nicholas-Schaub commented 6 years ago

I misspoke. TensorFlow.registeredOpList() is the method I meant to say. I have already parsed the byte array out, and from every check I've made, it matches the Python implementation. I'm just going to make a function that builds a graph like it does in Python and checks the input values for each function against the values given from registeredOpList.

asimshankar commented 6 years ago

@up-to-you @Nicholas-Schaub : Thanks for your interest. We haven't published a roadmap yet. So far we've been mostly interested in being able to "deploy" models typically architected in Python (often trained, but at least designed) into other languages such as Java.

The next step for the Java API is creating the op functions (#16120 is being worked on - thanks @karllessard @kbsriram ). However, we have not yet hashed out a timeline for building higher level APIs on top of that. That said, this is something that can be built on top of the lower level APIs that we do have, so if anyone wants to take a stab at it ... đź‘Ť

To be perfectly honest, it is unlikely that we'll have a significant change in the state of the Java API by June, but hopefully we'll have more of a plan to share by then (CC @ewilderj )

up-to-you commented 6 years ago

@asimshankar thanks for your information ! if I understand correctly - #16120 will let us construct graph from scratch using Java ? If so, is there any barrier for constructing multilayered CNN ?

Thanks in advance.

karllessard commented 6 years ago

@up-to-you, there are a few more pull requests upcoming after #16120 to be able to construct a multilayered CNN from scratch in Java using a rich API.

But like @asimshankar said, even with that, there will still be some additional work to do to reach the maturity of the Python API as it contains more logic than what is exposed by the core library, shared by all the clients. For example, gradient backpropagation will still be more easier in Python than in Java (while still feasible). It would be nice if somebody could take a look at this part!

Nicholas-Schaub commented 6 years ago

Well...I'm glad I stumbled upon this. I thought that the logic for backpropagation would be in the core library, and the main hurtle was creating functions to use the core library. Looks like I'm building and training in Python and importing into Java.

asimshankar commented 6 years ago

@Nicholas-Schaub : For now, yeah, building and training in Python and exporting to Java for inference is probably best.

Though, see the Java samples, in particular the linked slides with speaker notes, and the one trivial example of building the model in Python but actually training in Java.

up-to-you commented 6 years ago

@karllessard @asimshankar regarding the information you provided (thanks a lot !), i think its better to emphasize efforts on model training maturity, using Java API. In this case we have advantages of both worlds :

  1. declaring model using full-fledged, short, readable Python syntax
  2. training NN and inference with Java, using its performance, multithreading, big-data collaboration etc.

@asimshankar can you please provide video / source link, from where does this slides come ?

asimshankar commented 6 years ago

The slides are linked to in the README I pointed to, but here they are anyway

They were from a talk I gave in a Java Users Group meeting. I don't think there is a video link.

karllessard commented 6 years ago

Just to add something about this: other than the ubiquitous differences between the two languages, what is really interesting about having a Java graph building API compared to Python is the way it enforces tensor type checking at compile time (by using generics). So you know exactly what datatype you are dealing with at the output of an operation and what you can possibly do with it. So I think current efforts are not done in vain... or at least I hope ;)

Implementing the core ops in Java is a big step forward for having a mature client library and yes @Nicholas-Schaub, it will be possible to do backpropagation using the training ops, for example. But it will not be as easy as in Python until we figure out how to extract and expose the logic implemented in its client library, like its gradient descent optimizer.

Nicholas-Schaub commented 6 years ago

@karllessard If the issue is just figuring out how to expose the logic, isn't it just a matter of parsing the `registeredOpList' to get a list of functions and their inputs/outputs and writing a rudimentary translator to make sure that the appropriate inputs and outputs are being sent/received? The way it was discussed above, I thought that we would have to implement the gradient descent optimizer. My approach was just to parse the op list and write a generic graph building class that shows which operations are available and what inputs/attributes are needed. If the gradient descent functions are implemented in the core library, then it seems like it's just a matter of then building a simple class to cycle through layers for backpropagation. The hardest part for me seemed like it was going to be parsing the operations list, and then I could build a couple simple classes to build and train.

Nicholas-Schaub commented 6 years ago

My thought in implementing this wouldn't be something quite as nice as what Python currently has, but it would be enough to build a graph and train it. During the graph building phase, the individual elements would be added to a JSON string, and then the graph could be built based off the JSON string and checked for errors using the info we get from parsing the op list.

karllessard commented 6 years ago

@Nicholas-Schaub

isn't it just a matter of parsing the registeredOpList...

It is a bit more tricky than that. The registeredOpList does not provides all the required information to classify the ops properly (for instance, their "group"). This is why it has been decided to import them from a C++ process instead, that links to the individual libraries and generates Java classes for their ops at compile-time. PR #16120 and those upcoming are about this.

Just if you are curious, you might find a snapshot of the ops I have generated (and never tested) a long time ago from a intermediate version of this generator here.

Nicholas-Schaub commented 6 years ago

Does the grouping matter? I thought having the necessary information to build a function using Graph.opBuilder would have been enough. It seems like this is how the current state of the java side of things imports pretrained networks. Is there ambiguity in function handles between the different groupings? Why isn't having the names of all functions with corresponding inputs and attributes sufficient to use the opBuilder?

I apologize for drawing out the conversation, but it's been incredibly helpful thus far. Thank you for the link.

karllessard commented 6 years ago

Does the grouping matter?

Grouping doesn't matter at the functional level but it does matter at the API level. By this I mean that if you want to list and create classes just parsing the registeredOpList, it will work but you'll endup with a single package (group) of 600 classes or so, which would not be usable/acceptable as an official API for Tensorflow (just think how the auto-complete feature of popular IDEs will react on this). But for personal use, yes that'll do.

I apologize for drawing out the conversation, but it's been incredibly helpful thus far.

No problem it's a real pleasure, we can continue that discussion on a more private channel if you are interested, by joining this group.

up-to-you commented 6 years ago

@karllessard can you please shed some light on other pull requests planned after #16120 which will allow to construct multilayered CNN ? I'm gonna make some performance benchmarks in comparison to python impl's, since training elapsed time depends not only on C++/CUDA implementation, but on fetching and treatment of data too (before feeding it to CNN). And I make big bets, that in this part of whole process, Java will surpass Pythonish approach.

P.s. it will be more clearly for results if whole NN lifecycle will be build using Java. Just for some reflection on an abstract level Python vs Java benchmarks

asimshankar commented 6 years ago

@up-to-you : FYI: if you use the tf.data APIs to feed data to your model, then all the data is read, processed, and fed by the TensorFlow runtime, so the frontend language is unlikely to be a bottleneck. Long story short, it will generally be possible to get the same performance irrespective of frontend language.

karllessard commented 6 years ago

@up-to-you : very interesting, indeed. Asim brought an interesting point with the tf.data APIs but it would still be very nice to benchmark the performances of the Java client independently on this.

Timewise, #16120 has been accepted and is just waiting to be merged. After this, the target is that I come up with another PR by the end of the month which will actually generates the Op classes in the libtensorflow jar.

From there, you'll be able to build a graph in Java using those classes. More PR(s) will still come after to wrap those classes with a builder-like API but functionally, they should be ready to be used directly.

saudet commented 6 years ago

BTW, it's already possible to use the full C and C++ APIs with the JavaCPP Presets for TensorFlow, and we can pretty much do anything we want with that including building graphs and accessing the ops, for example: https://tebesu.github.io/posts/Training-a-TensorFlow-graph-in-C++-API https://matrices.io/training-a-deep-neural-network-using-only-tensorflow-c/

If there is anything missing from the bindings though, it should be a simple matter to add, so please do let me know! I'm very interested in making C++ libraries usable from Java and in understanding what is lacking, the difficulties, etc. So any feedback is welcome! Thanks

up-to-you commented 6 years ago

@saudet, First of all, its awesome, really! But, as @karllessard mentioned - there are a lot of logic, implemented at python level. For example i can't find api, that allows to write something like this:

l1 = tf.layers.dense(x, L1, activation = tf.nn.relu, use_bias = True ) l2 = tf.layers.dense(l1, L2, activation = tf.nn.relu , use_bias = True ) ...

and, honestly, unfortunately, i don't know how to implement same logic, using existing Java api in Tensorflow project, nor in your bindings.

saudet commented 6 years ago

Thanks! Yes, I am aware a lot is implemented only in Python, but at some point it needs to be implemented in either C++ or in Java. Imagine it gets implemented in a user-friendly API in C++, what would make you not use JavaCPP? What would still be missing? That's the kind of feedback I'm looking for. :)

Nicholas-Schaub commented 6 years ago

I'm glad I've held off working on making up my own solution to this problem since it sounds like things are starting to come down the pipe.

@saudet What would make me not use JavaCPP is that I need to do things in native Java. If it's included in a dll that's fine, otherwise it's a headache.

karllessard commented 6 years ago

@saudet, JavaCPP is a very interesting project indeed, but I think for tensorflow, Python client will always be a step ahead of both Java and C++ clients for training.

@kbsriram already thought of doing the same thing but with a PythonToJava flavour, I don’t know what would be the complexity of such work though.

saudet commented 6 years ago

@Nicholas-Schaub IMO, we're far from getting everything in place, so please keep looking at things! What bothers me though is that I had mapped the C++ API of TensorFlow API way back in 2015, but apparently this was not a satisfactory solution for Google (and I am still looking for an explanation as to why that is) and their engineers (mainly @asimshankar) started writing JNI code manually and building a custom API on top of that. I can see this is still in progress, first to match the functionality of the C++ API for the ops, and then eventually of the Python API.

So, anyway, all that to say, I would welcome any feedback about JavaCPP and what's missing. I mean, I do receive feedback from users saying that the C++ API isn't user-friendly, which is fair enough, but then why not build a user-friendly API on top of automatically generated wrappers like they've been doing for the Python API with SWIG? Why is there a need to write everything manually down to all the JNI functions?

@karllessard Yes, I've also been talking about that, and https://jyni.org/ is another project which could use our support and that could provide that. They've got NumPy running, adding TensorFlow would probably not be that hard, if we can actually get 1 or 2 engineers working on that full time that is. Again, it won't provide a Java-friendly API out of the box, but it would take care of generating all the nasty boilerplate code, so why not use, if not that exactly, something like that, at least?

up-to-you commented 6 years ago

Wow, it seems like #14094 merged, i'm staying tuned on next pull requests ! @karllessard @asimshankar thanks guys !

asimshankar commented 6 years ago

@saudet: Regarding "I'm still looking for an explanation as to why that is", I didn't know that you had ever asked for one :). My apologies if I missed some previous comment asking about this.

First some background:

The Java API implementation in this repository has a relatively small hand-written JNI wrapper over the C API for the lowest level constructs (Graph, Operation, Session). The work by @karllessard and others is not adding any additional JNI, but generating idiomatic pure-Java wrappers for all the TensorFlow operations by composing the lower level Java constructs. This is again very similar to how the Python API wrappers (tf.add, tf.gather etc.) are generated to use the Python constructs built on top of the C API. The same for Go. These language-specific generation tools make it easier to generate code that follow idioms of the target language. For example, in Java, generics are used to indicate the element-type of Tensor objects. It's a small amount of JNI to build the lowest level constructs and then a generator of pure Java code on top of that. It's not that "everything" is being written in JNI manually.

Long story short, there were a few options we had:

Each of them is attractive and has pros and cons. It was useful for us to have a Java API, particularly for executing models. In our judgement - given needs, the resources we have, and the fact that the API in this repository is something we (the TensorFlow team) support and maintain, the simplicity of the first approach - with fewer layers of abstraction, a small set of core constructs (backed by native code) upon which richer idiomatic APIs can be generated or built (in pure Java) made it appropriate.

I appreciate that there is some subjectivity involved in such a choice and that reasonable people can differ. However, I hope this at least provides a sense of where we were coming from. Looking ahead, we're figuring out the best way to get more community involvement in Java development, I'll be sure to reach out once we've figured out an appropriate forum for that. At that point, we can have a more detailed discussion (and possibly revisit these choices).

Also, your point about the C++ API not being user-friendly enough is well taken. Making graph construction APIs in C++ easier to use/navigate would be great, but is not currently on the top of our priority list.

saudet commented 6 years ago

@asimshankar Thank you for the thorough explanation and for clarifying the discussions that have been happening offline! My opinion though is that it is possible to design a C++ API that can be mapped automatically to other languages in a satisfactory manner. OpenCV is an example that is pretty close to that, and JavaCPP maps it pretty well. There are rough edges, but this is only because Java and Python are an afterthought of the C++ API. Given a bit more planning though, we could save many hours that are currently spent developing and maintaining essentially the same library in different languages. JavaCPP wraps only for Java, obviously, but there are no reasons why the same couldn't be done for other platforms. This is out of scope for TensorFlow, but it would be nice if we as a community could start developing more processes and tools like this to save time and effort. CLIF looks like an attempt at that, but I am unaware of anything significant actually using it...?

In any case, for now, I've bundled the official Java API in the JavaCPP Presets for TensorFlow: https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow#documentation This will make it easy for anyone to start with that API, but "upgrade" to the C++ API to access functionality only available there--without any build time or runtime conflict. If you ever need help integrating this into the Bazel build or anything, please let me know!

agibsonccc commented 6 years ago

@asimshankar I talked to rajat about this a few weeks ago and he actually encouraged collaboration.@saudet has done a ton of optimizations on the c++ side already (esp lower level pointer math with zero copy buffers rather than the manual copying that happens with the current java API) - we use those same optimizations in depth with our tensor library as well. If you don't mind I'm going to follow up directly again with him showing him this issue. We're trying to play ball here if we can. We are likely one of the few entities outside of google interested in making this work well. I'd like to see if we can open this up a bit.

asimshankar commented 6 years ago

@agibsonccc : Certainly, please do follow up. Those optimizations sound great, and we'd love to leverage expertise here. The details of how to do so would be worth working out, and having some off thread conversations before settling on something and updating this issue sounds great to me.

agibsonccc commented 6 years ago

Perfect. Just wanted to start a dialog. Someone reached out already. Will keep folks posted on concrete outcomes, thanks for the interest!

karllessard commented 6 years ago

Just FYI everyone, pull request #18192 has been created to generate the Java operators and it is a big step forward to have full-fledged support for TF graph building in Java. The PR is quite big and it might take some time before we get it merged but we'll do our best, thanks!

himsR commented 6 years ago

@karllessard , I want to do the graphbuilding using static functions(until tf rolls out the generated APIs), similar to what you have in the LabelImage example. It would be a complete training example with ops for both objective and say gradient descent. Since Java does not implement the autodiff functionality that python has, can you suggest any simple way of doing this (or do you have any POCs like the Labelimage one?).

saudet commented 6 years ago

@asimshankar Great! Looking forward to the discussions.

FWIW, TensorRT has a nice C++ API and JavaCPP maps it pretty well too: https://github.com/bytedeco/javacpp-presets/tree/master/tensorrt I'm not saying TensorFlow needs a C++ API though. I suppose tools for other platforms should catch up before it makes sense...

karllessard commented 6 years ago

@himsR , either with the upcoming Ops API wrappers or with current OperationBuilder & friends, the only thing that is supported in Java for building a graph is by using TensorFlow core operations. Anything else needs to be ported to the clients of each languages at some point (e.g. the C++ client has already started to port some of the Python functionalities).

I guess supporting those features will be the next step for the Java client, now that the Op wrappers are almost there. Right now, its improvement mainly relies on contributions so I suggest that you go on with building your graph, identify what is missing in your case and share it with us... or even better, write it down and submit your code :)

himsR commented 6 years ago

@karllessard thanks for the information. The op wrappers that you are writing , do they include the gradient ops as well? For example , something equivalent to the ops inside the math_grad.cc in the core ?

karllessard commented 6 years ago

@himsR : are you talking about math_grad.cc of the C++ client? If so, most of those ops come from the math_ops library so yes, they will be wrapped. The current scope for the first draft of wrappers is to cover the following libraries (that could be found here)

array_ops
candidate_sampling_ops
control_flow_ops
data_flow_ops
image_ops
io_ops
linalg_ops
logging_ops
math_ops
nn_ops
no_op
parsing_ops
random_ops
sparse_ops
state_ops
string_ops
training_ops
user_ops
himsR commented 6 years ago

@karllessard yes that's awesome. Since the above list does not include the gradient files, it would still be required to code all the gradients using ops from these apis. So yeah this should give all the ops required to build the backpropagation logic into java. I asked particularly about the gradients because I think at present client languages like python impelement all the gradients themselves(by calling and combining the normal ops) instead of calling the c core. So at present in Java, although you can call all the ops using the 'OperationBuilder' but you can't get the gradients that way. Thanks.

saudet commented 6 years ago

Hey, @karllessard, I have a question for you. I see from your pull requests #14094, #15928, #16120 and #18192 that you had to write almost everything in C++, but with JavaCPP, it would have been possible to do it all in Java. Had you been given the chance to do it in Java instead of C++, do you think it would have made things easier for you?

saudet commented 6 years ago

In any case, my point is that if we could offer developers the option of contributing code in Java instead of having them write most of the plumbing in C++, TensorFlow would get a much wider adoption from the Java community. Many Python developers can also write code in C++, but this is not typically the case of Java developers.

It's also one of the big differences between SWIG and JavaCPP. With SWIG, developers are forced to code in both C++ and the "scripting language" (Python, Java, etc). Instead, JavaCPP maps the C++ API wholesale, offering a complete and usable Java interface, without any need to write or make adjustments to the C++ code. BTW, if anyone knows of an alternative to access the full C++ API of TensorFlow from Java (or from any other platform for that matter, in C#, Go, Rust, JavaScript, etc), please let me know: I would welcome competition! :)

karllessard commented 6 years ago

Hi @saudet, sorry for the delay. I feel that there might be a little bit of misunderstanding here, please let me explain more in details. Sorry for the novel ;)

Had you been given the chance to do it in Java instead of C++, do you think it would have made things easier for you

Definitely, a challenge I had in C++ was to output Java source code efficiently, which could have been provided out-of-the-box from Java frameworks, such as JavaPoet.

The main reason why I had to go with C++ the generator the operation wrappers, as I told @Nicholas-Schaub previously in this thread, is to benefit from operation classification which, at that time, could only be achieved by only linking one core op library at a time to the generator binary and use that library as a package delimiter. Otherwise you'll end up having all 700+ ops in the same package, which is not convenient. That's the approach the C++ client was taking too. It was a bit hacky, in my opinion, but I'm not sure to see how JavaCPP would have help me doing otherwise here.

On this topic though, there have been some updates to this issue. Lately, the TF community has introduced a new layer of abstraction over the core ops definitions, called Api defs, which not only exposes classification information in proto buffers but also allows variation of the API per language for fine-tuning. With this new API framework, the wrapper generator could have been written in Java from the start. Now that there is only #18192 remaining to generator those wrappers, I guess we should continue in the current direction and maybe migrate that code to Java later.

if we could offer developers the option of contributing code in Java instead of having them write most of the plumbing in C++

And that is actually already the case. Once the wrappers are available, any addition or "plumbing" to the Java client could be written directly in Java. There might be a bit of JNI code to do here and there I guess, but features I can think so far shouldn't require it.

From what I understand, JavaCPP goal is to simplify access to native libraries without the need of writing JNI code by ourself or interfacing with proto buffers, is that right? So your idea is to have a fully-compliant C++ client that could be "wrapped" in Java as a replacement of the actual client or is it just to replace the JNI bridge? I have no doubt JavaCPP is more convenient that writing JNI code. Proto buffers, on the other hand, is easy to support. Also, how JavaCPP would it handle features that are unique to the Java, such as generics, Javadoc, etc.? IMHO, what really matters in the end is the quality of the interface exposed to the user and not how it was developed.

saudet commented 6 years ago

@karllessard Thanks for the insights! Unless the C++ API is designed in a way to let us generate automatically nice high-level APIs, there will always be a need to develop something on top. I agree with that.

I'm not familiar enough with TensorFlow to evaluate how much work there is still to be done with the C++ API to get the Java API to be as feature complete as the Python API, but looking at the amount of code that the SWIG interface files from TensorFlow generate (about 25000 lines), I'm guessing "a lot". Am I wrong?

JavaCPP basically provides access to everything C++. JNI is completely abstracted away, so the fact that it uses JNI isn't really relevant. Any other approach that I am aware of forces developers to get their hands dirty with C++. They don't offer a way to just use it from another language such as Java--with full support for reflection--whether it's one big API, or a bunch of smaller ones in "groups" (of operations, etc), which I call "presets": http://bytedeco.org/.

There is a Java API for protocol buffers, so that should be used whenever possible, sure. I'm not saying that using wrappers around C++ generated code is a better idea. :) Anyway, the concept of using C++ classes and templates from another language isn't new, but it's a road paved with failures and very limited success that has made many casualties over the decades, so it's hard to get people to even acknowledge that it's actually possible...

up-to-you commented 6 years ago

@karllessard can we expect tf.train.Example, tf.python_io.TFRecordWriter, tf.train.Feature and other tf.train.* types wrappers? This impl will blow up everyone, since it will shut the hole in Spark <-> Tensorflow integration. Until higher level api will be implemented in java.

karllessard commented 6 years ago

Hi @up-to-you , what is being ported right now are core ops that can be added to a neural network for training, i.e. most of the ops that are registered here.

AFAIK, what you are referring to are utilities to store example data that happens outside the network, so it won't be part of the current work (though you'll be able to read data stored in a TFRecord from the network using the TFRecordReader core op).

Good news is that nothing prevent a programmer to add Example & friends support right now in the Java client, I guess it is just a matter of creating a proto message from data provided in input. Some utilities though might require a pinch of JNI bindings (or what @saudet is currently proposing).

up-to-you commented 6 years ago

@karllessard I'll try my best in this way, but can you please provide some food for thought or some direction where i can start. Thanks in advance! P.s. e.g. can't find any information about in-depth proto-structure of TFRecord file.

karllessard commented 6 years ago

@up-to-you : Well, I haven't look too deeply in the Python code but it looks like it's invoking the core utility RecordWriter to accomplish the task of writing data. We should probably do the same by writing a new JNI binding for it.

Then, for supporting the Example format, I guess we could generate classes out of the protocol messages using a java_proto_library rule and maybe wrap their usage in a ExampleBuilder object?

asimshankar commented 6 years ago

@up-to-you: tf.train.Example is available in the org.tensorflow:proto maven artifact (see javadoc). That artifact contains all the TensorFlow protocol buffers for Java.

It would be great to work out a path to include full functionality by leveraging the best of @karllessard and @saudet 's work (and effectively utilizing JavaCPP). But we haven't gotten around to figuring out the details of that yet.

Perhaps you're willing to pioneer a first exploration towards that by updating the JavaCPP presets for TensorFlow so that it can provide a Java interface to the C++ RecordWriter class?

saudet commented 6 years ago

@asimshankar @karllessard Sounds like the perfect opportunity to try this out with JavaCPP! Thanks

@up-to-you I've updated the presets with RecordWriter in commit https://github.com/bytedeco/javacpp-presets/commit/e64724b5d194affeebf4c2934c0c4c557f3111ea. New snapshots should be available in a few hours: http://bytedeco.org/builds/ And a sample pom.xml file is available at: https://github.com/bytedeco/javacpp-presets/tree/master/tensorflow#sample-usage Let me know if you encounter any issues with that or have any questions. If this works well, I'm assuming we would next have to integrate JavaCPP into the Bazel build, and probably start small and/or somehow modularize the API, something I'm happy to help with!