-
Notifications
You must be signed in to change notification settings - Fork 839
Java JNI (JPype) Wrapper #2374
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
Java JNI (JPype) Wrapper #2374
Changes from all commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
79162bd
prototype disabling encoder / decoder
f2cd705
Merge env vars
6b33fd9
Remove check from handle_raw_custom_metric
2e4199d
Add some tests for jsonify
1172461
Add initial set of files for JavaJNI server
7006482
Add requirements.txt with JPype
8ffbf86
Add raw methods to Java wrapper
aa85d45
Bump version of Java wrapper
895aad1
Use String insted of byte[] for REST
13a6889
Change structure of get_request
bae280a
Fix defaults
bb45f65
Fix type annotations
82d07f1
Add Docker images for java-jni server
5cb2ca0
Update scripts to pass Java env vars
f676f67
Ignore _python folder
e05c236
Fixed debug message
51613fd
Add model-template-app example for JNI server
afa702c
Build fat JAR
aa880c4
Fix env variables in exec
3ccb426
Change image name
f623ce0
Add docs section on JNI gateway for Java
f8f09ce
Bump to 0.3.0
fa62108
Use released package
6bbd7cb
Remove version.txt
cc65e05
Fix backticks
c631789
Add note on PAYLOAD_PASSTHROUGH to docs
9e86e3a
Add example from model-template-app
664918f
Move constant outside
b42cdd7
Add test to build s2i image
30e1e08
Add helpers to deploy models using Helm chart
7474a5e
Add ignore to pre-commit to match Makefile in python/
1283bf8
Add mising s2i folder
96e3328
Fix tests for JNI gateway
e450db3
Add s2i helpers and fixture
bf51a8d
Run tests on Java wrapper
1cfc666
Build new version of legacy Java wrapper
d04e858
Rename test folder to java
3c10296
Fix tests and skip pure Java ones
b59831b
Remove deprecated TODO
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
# Packaging a Java model for Seldon Core using s2i | ||
|
||
In this guide, we illustrate the steps needed to wrap your own Java model in a | ||
docker image ready for deployment with Seldon Core using [source-to-image app | ||
s2i](https://github.com/openshift/source-to-image) and the JNI wrapper. | ||
|
||
The JNI wrapper leverages the [Python inference server](../python) to | ||
communicate through JNI with your Java model. | ||
The Python wrapper usually receives updates much faster than the [native Java | ||
one](../java/README.md). | ||
Therefore it allows you to have faster access to the latest Seldon Core | ||
features. | ||
|
||
If you are not familiar with s2i you can read [general instructions on using | ||
s2i](../wrappers/s2i.md) and then follow the steps below. | ||
|
||
## Step 1 - Install s2i | ||
|
||
[Download and install s2i](https://github.com/openshift/source-to-image#installation) | ||
|
||
* Prerequisites for using s2i are: | ||
* Docker | ||
* Git (if building from a remote git repo) | ||
|
||
To check everything is working you can run | ||
|
||
```bash | ||
s2i usage seldonio/s2i-java-jni-build:0.3.0 | ||
``` | ||
|
||
## Step 2 - Create your source code | ||
|
||
To use our s2i builder image to package your Java model you will need: | ||
|
||
* A Maven project that depends on `io.seldon.wrapper` library (>= `0.3.0`) | ||
* A class that implements `io.seldon.wrapper.api.SeldonPredictionService` for the type of component you are creating | ||
* .s2i/environment - model definitions used by the s2i builder to correctly wrap your model | ||
|
||
We will go into detail for each of these steps: | ||
|
||
### Maven Project | ||
Create a Spring Boot Maven project and include the dependency: | ||
|
||
```XML | ||
<dependency> | ||
<groupId>io.seldon.wrapper</groupId> | ||
<artifactId>seldon-core-wrapper</artifactId> | ||
<version>0.3.0</version> | ||
</dependency> | ||
``` | ||
|
||
A full example can be found at `incubating/wrappers/s2i/java-jni/test/model-template-app/pom.xml`. | ||
|
||
### Prediction Class | ||
To handle requests to your model or other component you need to implement one | ||
or more of the methods in `io.seldon.wrapper.api.SeldonPredictionService`, in | ||
particular: | ||
|
||
```java | ||
default public SeldonMessage predict(SeldonMessage request); | ||
default public SeldonMessage route(SeldonMessage request); | ||
default public SeldonMessage sendFeedback(Feedback request); | ||
default public SeldonMessage transformInput(SeldonMessage request); | ||
default public SeldonMessage transformOutput(SeldonMessage request); | ||
default public SeldonMessage aggregate(SeldonMessageList request); | ||
``` | ||
|
||
There is a full H2O example in | ||
`examples/models/h2o_mojo/src/main/java/io/seldon/example/h2o/model`, whose | ||
implementation is shown below: | ||
|
||
```java | ||
public class H2OModelHandler implements SeldonPredictionService { | ||
private static Logger logger = LoggerFactory.getLogger(H2OModelHandler.class.getName()); | ||
EasyPredictModelWrapper model; | ||
|
||
public H2OModelHandler() throws IOException { | ||
MojoReaderBackend reader = | ||
MojoReaderBackendFactory.createReaderBackend( | ||
getClass().getClassLoader().getResourceAsStream( | ||
"model.zip"), | ||
MojoReaderBackendFactory.CachingStrategy.MEMORY); | ||
MojoModel modelMojo = ModelMojoReader.readFrom(reader); | ||
model = new EasyPredictModelWrapper(modelMojo); | ||
logger.info("Loaded model"); | ||
} | ||
|
||
@Override | ||
public SeldonMessage predict(SeldonMessage payload) { | ||
List<RowData> rows = H2OUtils.convertSeldonMessage(payload.getData()); | ||
List<AbstractPrediction> predictions = new ArrayList<>(); | ||
for(RowData row : rows) | ||
{ | ||
try | ||
{ | ||
BinomialModelPrediction p = model.predictBinomial(row); | ||
predictions.add(p); | ||
} catch (PredictException e) { | ||
logger.info("Error in prediction ",e); | ||
} | ||
} | ||
DefaultData res = H2OUtils.convertH2OPrediction(predictions, payload.getData()); | ||
|
||
return SeldonMessage.newBuilder().setData(res).build(); | ||
} | ||
|
||
} | ||
|
||
``` | ||
|
||
The above code: | ||
|
||
* Loads a model from the local resources folder on startup | ||
* Converts the proto buffer message into H2O RowData using provided utility classes. | ||
* Runs a BionomialModel prediction and converts the result back into a `SeldonMessage` for return | ||
|
||
#### H2O Helper Classes | ||
|
||
We provide H2O utility class `io.seldon.wrapper.utils.H2OUtils` in | ||
seldon-core-wrapper to convert to and from the seldon-core proto buffer message | ||
types. | ||
|
||
#### DL4J Helper Classes | ||
|
||
We provide a DL4J utility class `io.seldon.wrapper.utils.DL4JUtils` in | ||
seldon-core-wrapper to convert to and from the seldon-core proto buffer message | ||
types. | ||
|
||
### .s2i/environment | ||
|
||
Define the core parameters needed by our Java S2I images to wrap your model. | ||
An example is: | ||
|
||
```bash | ||
API_TYPE=REST | ||
SERVICE_TYPE=MODEL | ||
JAVA_IMPORT_PATH=io.seldon.example.model.ExampleModelHandler | ||
``` | ||
|
||
These values can also be provided or overridden on the command line when building the image. | ||
|
||
## Step 3 - Build your image | ||
|
||
Use `s2i build` to create your Docker image from source code. | ||
You will need Docker installed on the machine and optionally git if your source | ||
code is in a public git repo. | ||
|
||
Using s2i you can build directly from a git repo or from a local source folder. | ||
See the [s2i | ||
docs](https://github.com/openshift/source-to-image/blob/master/docs/cli.md#s2i-build) | ||
for further details. | ||
The general format is: | ||
|
||
```bash | ||
s2i build \ | ||
<git-repo | src-folder> \ | ||
seldonio/s2i-java-jni-build:0.3.0 \ | ||
--runtime-image seldonio/s2i-java-jni-runtime:0.3.0 \ | ||
<my-image-name> | ||
``` | ||
|
||
An example invocation using the test template model inside `seldon-core`: | ||
|
||
```bash | ||
s2i build \ | ||
https://github.com/seldonio/seldon-core.git \ | ||
--context-dir=incubating/wrappers/s2i/java-jni/test/model-template-app \ | ||
seldonio/s2i-java-jni-build:0.3.0 \ | ||
--runtime-image seldonio/s2i-java-jni-runtime:0.3.0 \ | ||
jni-model-template:0.1.0 | ||
``` | ||
|
||
The above s2i build invocation: | ||
|
||
* uses the `seldon-core` [GitHub repo](https://github.com/seldonio/seldon-core) | ||
and the directory `incubating/wrappers/s2i/java-jni/test/model-template-app` | ||
inside that repo. | ||
* uses the builder image `seldonio/s2i-java-jni-build` | ||
* uses the runtime image `seldonio/s2i-java-jni-runtime` | ||
* creates a docker image `jni-template-model` | ||
|
||
|
||
For building from a local source folder, an example where we clone the seldon-core repo: | ||
|
||
```bash | ||
git clone https://github.com/seldonio/seldon-core.git | ||
cd seldon-core | ||
s2i build \ | ||
incubating/wrappers/s2i/java-jni/test/model-template-app \ | ||
seldonio/s2i-java-jni-build:0.3.0 \ | ||
--runtime-image seldonio/s2i-java-jni-runtime:0.3.0 \ | ||
jni-model-template:0.1.0 | ||
``` | ||
|
||
For more help see: | ||
|
||
```bash | ||
s2i usage seldonio/s2i-java-jni-build:0.3.0 | ||
s2i build --help | ||
``` | ||
|
||
## Reference | ||
|
||
## Environment Variables | ||
The required environment variables understood by the builder image are | ||
explained below. | ||
You can provide them in the `.s2i/environment` file or on the `s2i build` | ||
command line. | ||
|
||
### JAVA_IMPORT_PATH | ||
|
||
Import path for your Java model implementation. | ||
For instance, in the example above, this would be | ||
`io.seldon.example.model.ExampleModelHandler`. | ||
|
||
### API_TYPE | ||
|
||
API type to create. | ||
Can be REST or GRPC. | ||
|
||
### SERVICE_TYPE | ||
|
||
The service type being created. | ||
Available options are: | ||
|
||
* MODEL | ||
* ROUTER | ||
* TRANSFORMER | ||
* COMBINER | ||
|
||
|
||
## Creating different service types | ||
|
||
### MODEL | ||
|
||
* [A minimal skeleton for model source code](https://github.com/SeldonIO/seldon-core/tree/master/incubating/wrappers/s2i/java/test/model-template-app) | ||
* [Example H2O MOJO](../examples/h2o_mojo.html) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.