Repository: deepjavalibrary/djl
Pull request #1526 (2022-03-15 00:16:10)

Building DJL For aarch64
## Description ##

This PR adds support for compiling/building Pytorch JNI for ```aarch64``` ARM architecture.

### Changelist ###
* Adding aarch64 cross-compiler dependencies to ```build-pytorch-jni-linux``` in github action
* Get Python 3.6 to make ```python3 get-pip.py``` to get the github action to work (open to just making the script compatible with the latest version)
* Moved ```files.each``` in ```prepareNativeLib(...)``` to a separate function
* Download the necessary dependencies and copy native lib if ```aarch64``` specific
* Updated Pytorch version to ```1.10.2```

### Testing ###
* Ran ```CXX=aarch64-linux-gnu-gcc ./gradlew compileJNI -Paarch64 -Ppt_version=$PYTORCH_VERSION``` locally to verify build succeeded. 
* Ran github actions in private repository and succeeded up to the AWS Credentials step (at this point it's been built successfully)


Patch:
diff --git a/.github/workflows/native_jni_s3_pytorch.yml b/.github/workflows/native_jni_s3_pytorch.yml
index ae9b6ee7a..5aeeb4e4d 100644
--- a/.github/workflows/native_jni_s3_pytorch.yml
+++ b/.github/workflows/native_jni_s3_pytorch.yml
@@ -47,7 +47,6 @@ jobs:
           PYTORCH_VERSION=${PYTORCH_VERSION:-$(cat gradle.properties | awk -F '=' '/pytorch_version/ {print $2}')}
           aws s3 sync engines/pytorch/pytorch-native/jnilib s3://djl-ai/publish/pytorch/${PYTORCH_VERSION}/jnilib
           aws cloudfront create-invalidation --distribution-id E371VB8JQ6NRVY --paths "/pytorch/${PYTORCH_VERSION}/jnilib*"
-
   build-pytorch-jni-linux:
     if: github.repository == 'deepjavalibrary/djl'
     runs-on: ubuntu-latest
@@ -67,7 +66,7 @@ jobs:
       - name: Install Environment
         run: |
           apt-get update
-          DEBIAN_FRONTEND=noninteractive apt-get install -y locales cmake curl unzip software-properties-common
+          DEBIAN_FRONTEND=noninteractive apt-get install -y locales cmake curl unzip software-properties-common gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
           add-apt-repository -y ppa:deadsnakes/ppa
           apt-get update
           apt-get install -y python3 python3-distutils
@@ -85,6 +84,8 @@ jobs:
           ./gradlew :engines:pytorch:pytorch-native:compileJNI -Pcu10 -Ppt_version=$PYTORCH_VERSION
           ./gradlew :engines:pytorch:pytorch-native:cleanJNI
           ./gradlew :engines:pytorch:pytorch-native:compileJNI -Pcu11 -Ppt_version=$PYTORCH_VERSION
+          ./gradlew :engines:pytorch:pytorch-native:cleanJNI
+          CXX=aarch64-linux-gnu-gcc ./gradlew :engines:pytorch:pytorch-native:compileJNI -Paarch64 -Ppt_version=$PYTORCH_VERSION
       - name: Configure AWS Credentials
         uses: aws-actions/configure-aws-credentials@v1
         with:
diff --git a/.github/workflows/native_s3_fasttext.yml b/.github/workflows/native_s3_fasttext.yml
index 870f841e6..46eea773c 100644
--- a/.github/workflows/native_s3_fasttext.yml
+++ b/.github/workflows/native_s3_fasttext.yml
@@ -57,6 +57,7 @@ jobs:
             ${{ runner.os }}-gradle-
       - name: Release JNI prep
         run: |
+          export PYTORCH_PRECXX11=true
           ./gradlew :extensions:fasttext:compileJNI
           ./gradlew -Pjni :extensions:fasttext:test
       - name: Configure AWS Credentials
diff --git a/README.md b/README.md
index 9de05079d..c1db50354 100644
--- a/README.md
+++ b/README.md
@@ -88,6 +88,7 @@ The following pseudocode demonstrates running training:
 
 ## Release Notes
 
+* [0.16.0](https://github.com/deepjavalibrary/djl/releases/tag/v0.16.0) ([Code](https://github.com/deepjavalibrary/djl/tree/v0.16.0))
 * [0.15.0](https://github.com/deepjavalibrary/djl/releases/tag/v0.15.0) ([Code](https://github.com/deepjavalibrary/djl/tree/v0.15.0))
 * [0.14.0](https://github.com/deepjavalibrary/djl/releases/tag/v0.14.0) ([Code](https://github.com/deepjavalibrary/djl/tree/v0.14.0))
 * [0.13.0](https://github.com/deepjavalibrary/djl/releases/tag/v0.13.0) ([Code](https://github.com/deepjavalibrary/djl/tree/v0.13.0))
diff --git a/api/README.md b/api/README.md
index 6139483c5..85ac02b1c 100644
--- a/api/README.md
+++ b/api/README.md
@@ -35,7 +35,7 @@ You can pull the DJL API from the central Maven repository by including the foll
 <dependency>
     <groupId>ai.djl</groupId>
     <artifactId>api</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
 
@@ -45,7 +45,7 @@ For testing the current nightly build, use the following:
 <dependency>
     <groupId>ai.djl</groupId>
     <artifactId>api</artifactId>
-    <version>0.16.0-SNAPSHOT</version>
+    <version>0.17.0-SNAPSHOT</version>
 </dependency>
 ```
 
diff --git a/basicdataset/README.md b/basicdataset/README.md
index 56306135f..b291e9439 100644
--- a/basicdataset/README.md
+++ b/basicdataset/README.md
@@ -39,7 +39,7 @@ You can pull the module from the central Maven repository by including the follo
 <dependency>
     <groupId>ai.djl</groupId>
     <artifactId>basicdataset</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
 
diff --git a/basicdataset/src/main/java/ai/djl/basicdataset/nlp/AmazonReview.java b/basicdataset/src/main/java/ai/djl/basicdataset/nlp/AmazonReview.java
index 07ca83598..6eecaa5b2 100644
--- a/basicdataset/src/main/java/ai/djl/basicdataset/nlp/AmazonReview.java
+++ b/basicdataset/src/main/java/ai/djl/basicdataset/nlp/AmazonReview.java
@@ -22,6 +22,7 @@ import ai.djl.util.Progress;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import org.apache.commons.csv.CSVFormat;
 
@@ -58,7 +59,7 @@ public class AmazonReview extends CsvDataset {
 
         Map<String, String> filter = new ConcurrentHashMap<>();
         filter.put("dataset", datasetName);
-        Artifact artifact = mrl.match(filter);
+        Artifact artifact = Objects.requireNonNull(mrl.match(filter));
         mrl.prepare(artifact, progress);
 
         Path dir = mrl.getRepository().getResourceDirectory(artifact);
@@ -90,7 +91,7 @@ public class AmazonReview extends CsvDataset {
             repository = BasicDatasets.REPOSITORY;
             groupId = BasicDatasets.GROUP_ID;
             artifactId = ARTIFACT_ID;
-            csvFormat = CSVFormat.TDF.withQuote(null).withHeader();
+            csvFormat = CSVFormat.TDF.builder().setQuote(null).setHeader().build();
             datasetName = "us_Digital_Software";
         }
 
diff --git a/basicdataset/src/main/java/ai/djl/basicdataset/tabular/AirfoilRandomAccess.java b/basicdataset/src/main/java/ai/djl/basicdataset/tabular/AirfoilRandomAccess.java
index 796e1ac27..49cfe4016 100644
--- a/basicdataset/src/main/java/ai/djl/basicdataset/tabular/AirfoilRandomAccess.java
+++ b/basicdataset/src/main/java/ai/djl/basicdataset/tabular/AirfoilRandomAccess.java
@@ -120,7 +120,6 @@ public final class AirfoilRandomAccess extends CsvDataset {
         int length = selected.size();
         ByteBuffer bb = manager.allocateDirect(length * 4);
         FloatBuffer buf = bb.asFloatBuffer();
-        int index = 0;
         for (Feature feature : selected) {
             String name = feature.getName();
             float value = Float.parseFloat(record.get(name));
@@ -128,7 +127,6 @@ public final class AirfoilRandomAccess extends CsvDataset {
                 value = (value - mean.get(name)) / std.get(name);
             }
             buf.put(value);
-            ++index;
         }
         buf.rewind();
         return new NDList(manager.create(buf, new Shape(length)));
@@ -179,7 +177,13 @@ public final class AirfoilRandomAccess extends CsvDataset {
             groupId = BasicDatasets.GROUP_ID;
             artifactId = ARTIFACT_ID;
             usage = Usage.TRAIN;
-            csvFormat = CSVFormat.TDF.withHeader(COLUMNS).withIgnoreHeaderCase().withTrim();
+            csvFormat =
+                    CSVFormat.TDF
+                            .builder()
+                            .setHeader(COLUMNS)
+                            .setIgnoreHeaderCase(true)
+                            .setTrim(true)
+                            .build();
         }
 
         /** {@inheritDoc} */
diff --git a/basicdataset/src/main/java/ai/djl/basicdataset/tabular/AmesRandomAccess.java b/basicdataset/src/main/java/ai/djl/basicdataset/tabular/AmesRandomAccess.java
index ded11c358..9ddc8a6e0 100644
--- a/basicdataset/src/main/java/ai/djl/basicdataset/tabular/AmesRandomAccess.java
+++ b/basicdataset/src/main/java/ai/djl/basicdataset/tabular/AmesRandomAccess.java
@@ -112,7 +112,13 @@ public class AmesRandomAccess extends CsvDataset {
             artifactId = ARTIFACT_ID;
             usage = Usage.TRAIN;
             csvFormat =
-                    CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase().withTrim();
+                    CSVFormat.DEFAULT
+                            .builder()
+                            .setHeader()
+                            .setSkipHeaderRecord(true)
+                            .setIgnoreHeaderCase(true)
+                            .setTrim(true)
+                            .build();
         }
 
         /** {@inheritDoc} */
diff --git a/bom/README.md b/bom/README.md
index e5f9f535b..b9ead760c 100644
--- a/bom/README.md
+++ b/bom/README.md
@@ -22,7 +22,7 @@ will need to mention the type as pom and the scope as import) as the following:
         <dependency>
             <groupId>ai.djl</groupId>
             <artifactId>bom</artifactId>
-            <version>0.15.0</version>
+            <version>0.16.0</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
@@ -38,7 +38,7 @@ will need to mention the type as pom and the scope as import) as the following:
         <dependency>
             <groupId>ai.djl</groupId>
             <artifactId>bom</artifactId>
-            <version>0.15.0</version>
+            <version>0.16.0</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
@@ -70,7 +70,7 @@ will need to mention the type as pom and the scope as import) as the following:
 - First you need add BOM into your build.gradle file as the following:
 
 ```
-    implementation platform("ai.djl:bom:0.15.0")
+    implementation platform("ai.djl:bom:0.16.0")
 ```
 
 - Then you import the desired DJL modules into to you pom.xml file (no version is needed):
diff --git a/djl-zero/README.md b/djl-zero/README.md
index 608ea2c9a..05cf15b26 100644
--- a/djl-zero/README.md
+++ b/djl-zero/README.md
@@ -34,6 +34,6 @@ You can pull the module from the central Maven repository by including the follo
 <dependency>
     <groupId>ai.djl</groupId>
     <artifactId>djl-zero</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
diff --git a/docs/development/development_guideline.md b/docs/development/development_guideline.md
index db573c7ed..aed0c95f0 100644
--- a/docs/development/development_guideline.md
+++ b/docs/development/development_guideline.md
@@ -159,7 +159,7 @@ You can create your own NDArray renderer as follows:
 Please make sure to:
 
 - Check the "On-demand" option, which causes IntelliJ to only render the NDArray when you click on the variable.
-- Change the "Use following expression" field to something like [toDebugString(100, 10, 10, 20)](https://javadoc.io/static/ai.djl/api/0.15.0/ai/djl/ndarray/NDArray.html#toDebugString-int-int-int-int-)
+- Change the "Use following expression" field to something like [toDebugString(100, 10, 10, 20)](https://javadoc.io/static/ai.djl/api/0.16.0/ai/djl/ndarray/NDArray.html#toDebugString-int-int-int-int-)
 if you want to adjust the range of NDArray's debug output.
 
 ## Common Problems
diff --git a/docs/development/how_to_use_dataset.md b/docs/development/how_to_use_dataset.md
index 3d0152630..93c31c891 100644
--- a/docs/development/how_to_use_dataset.md
+++ b/docs/development/how_to_use_dataset.md
@@ -108,8 +108,8 @@ api group: 'org.apache.commons', name: 'commons-csv', version: '1.7'
 In order to extend the dataset, the following dependencies are required:
 
 ```
-api "ai.djl:api:0.15.0"
-api "ai.djl:basicdataset:0.15.0"
+api "ai.djl:api:0.16.0"
+api "ai.djl:basicdataset:0.16.0"
 ```
 
 There are four parts we need to implement for CSVDataset.
diff --git a/docs/development/memory_management.md b/docs/development/memory_management.md
index 99d48043f..1e39862d7 100644
--- a/docs/development/memory_management.md
+++ b/docs/development/memory_management.md
@@ -37,7 +37,7 @@ The intermediate NDArrays involving in training case are usually
 
 In general, all the parameters in the model should be associated with Model level NDManager.
 All of the input and output NDArrays should be associated with one NDManager which is one level down to the model NDManager.
-Please check if you call [batch.close()](https://javadoc.io/static/ai.djl/api/0.15.0/ai/djl/training/dataset/Batch.html#close--)
+Please check if you call [batch.close()](https://javadoc.io/static/ai.djl/api/0.16.0/ai/djl/training/dataset/Batch.html#close--)
 to release one batch of the dataset at the end of each batch.
 If you still see the memory grows as the training process goes, it is most likely that intermediate NDArrays are attached to the Model(Block) parameter level.
 As a result, those NDArrays would not closed until the training is finished.
diff --git a/docs/development/troubleshooting.md b/docs/development/troubleshooting.md
index 764473c14..6959ecf99 100644
--- a/docs/development/troubleshooting.md
+++ b/docs/development/troubleshooting.md
@@ -28,7 +28,7 @@ For example, adding MXNet engine dependencies:
 Gradle:
 
 ```
-implementation "ai.djl.mxnet:mxnet-engine:0.15.0"
+implementation "ai.djl.mxnet:mxnet-engine:0.16.0"
 // See https://github.com/deepjavalibrary/djl/blob/master/engines/mxnet/mxnet-engine/README.md for more MXNet library selection options
 runtimeOnly "ai.djl.mxnet:mxnet-native-auto:1.8.0"
 ```
diff --git a/docs/hybrid_engine.md b/docs/hybrid_engine.md
index dbeb34fc6..31348eb81 100644
--- a/docs/hybrid_engine.md
+++ b/docs/hybrid_engine.md
@@ -22,17 +22,17 @@ to run in a hybrid mode:
 To use it along with Apache MXNet for additional API support, add the following two dependencies:
 
 ```
-runtimeOnly "ai.djl.mxnet:mxnet-engine:0.15.0"
+runtimeOnly "ai.djl.mxnet:mxnet-engine:0.16.0"
 ```
 
 You can also use PyTorch or TensorFlow Engine as the supplemental engine by adding their corresponding dependencies.
 
 ```
-runtimeOnly "ai.djl.pytorch:pytorch-engine:0.15.0"
+runtimeOnly "ai.djl.pytorch:pytorch-engine:0.16.0"
 ```
 
 ```
-runtimeOnly "ai.djl.tensorflow:tensorflow-engine:0.15.0"
+runtimeOnly "ai.djl.tensorflow:tensorflow-engine:0.16.0"
 ```
 
 ## How Hybrid works
diff --git a/docs/load_model.md b/docs/load_model.md
index 5aacccbe1..c7ac1ae52 100644
--- a/docs/load_model.md
+++ b/docs/load_model.md
@@ -181,7 +181,7 @@ Here is a few tips you can use to help you debug model loading issue:
 See [here](development/configure_logging.md#configure-logging-level) for how to enable debug log
 
 #### List models programmatically in your code
-You can use [ModelZoo.listModels()](https://javadoc.io/static/ai.djl/api/0.15.0/ai/djl/repository/zoo/ModelZoo.html#listModels--) API to query available models.
+You can use [ModelZoo.listModels()](https://javadoc.io/static/ai.djl/api/0.16.0/ai/djl/repository/zoo/ModelZoo.html#listModels--) API to query available models.
 
 #### List available models using DJL command line
 
diff --git a/engines/dlr/dlr-engine/README.md b/engines/dlr/dlr-engine/README.md
index 0ed416227..b16a4f5ee 100644
--- a/engines/dlr/dlr-engine/README.md
+++ b/engines/dlr/dlr-engine/README.md
@@ -29,13 +29,13 @@ The javadocs output is generated in the `build/doc/javadoc` folder.
 ## Installation
 You can pull the DLR engine from the central Maven repository by including the following dependency:
 
-- ai.djl.dlr:dlr-engine:0.15.0
+- ai.djl.dlr:dlr-engine:0.16.0
 
 ```xml
 <dependency>
     <groupId>ai.djl.dlr</groupId>
     <artifactId>dlr-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
diff --git a/engines/ml/xgboost/README.md b/engines/ml/xgboost/README.md
index e879b793b..7319b9832 100644
--- a/engines/ml/xgboost/README.md
+++ b/engines/ml/xgboost/README.md
@@ -37,13 +37,13 @@ XGBoost can only run on top of the Linux/Mac machine. User can build from source
 ## Installation
 You can pull the XGBoost engine from the central Maven repository by including the following dependency:
 
-- ai.djl.ml.xgboost:xgboost:0.15.0
+- ai.djl.ml.xgboost:xgboost:0.16.0
 
 ```xml
 <dependency>
     <groupId>ai.djl.ml.xgboost</groupId>
     <artifactId>xgboost</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
diff --git a/engines/mxnet/mxnet-engine/README.md b/engines/mxnet/mxnet-engine/README.md
index 5d02398d0..1b9ad35e5 100644
--- a/engines/mxnet/mxnet-engine/README.md
+++ b/engines/mxnet/mxnet-engine/README.md
@@ -7,7 +7,7 @@ This module contains the Deep Java Library (DJL) EngineProvider for Apache MXNet
 We don't recommend that developers use classes in this module directly. Use of these classes
 will couple your code with Apache MXNet and make switching between engines difficult. Even so,
 developers are not restricted from using engine-specific features. For more information,
-see [NDManager#invoke()](https://javadoc.io/static/ai.djl/api/0.15.0/ai/djl/ndarray/NDManager.html#invoke-java.lang.String-ai.djl.ndarray.NDArray:A-ai.djl.ndarray.NDArray:A-ai.djl.util.PairList-).
+see [NDManager#invoke()](https://javadoc.io/static/ai.djl/api/0.16.0/ai/djl/ndarray/NDManager.html#invoke-java.lang.String-ai.djl.ndarray.NDArray:A-ai.djl.ndarray.NDArray:A-ai.djl.util.PairList-).
 
 ## Documentation
 
@@ -32,7 +32,7 @@ You can pull the MXNet engine from the central Maven repository by including the
 <dependency>
     <groupId>ai.djl.mxnet</groupId>
     <artifactId>mxnet-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
diff --git a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/Symbol.java b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/Symbol.java
index 8fcc92e50..0c927221c 100644
--- a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/Symbol.java
+++ b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/Symbol.java
@@ -217,9 +217,6 @@ public class Symbol extends NativeResource<Pointer> {
      */
     public Map<String, Shape> inferShape(PairList<String, Shape> pairs) {
         List<List<Shape>> shapes = JnaUtils.inferShape(this, pairs);
-        if (shapes == null) {
-            throw new IllegalArgumentException("Cannot infer shape based on the data provided!");
-        }
         List<Shape> argShapes = shapes.get(0);
         List<Shape> outputShapes = shapes.get(1);
         List<Shape> auxShapes = shapes.get(2);
diff --git a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/jna/JnaUtils.java b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/jna/JnaUtils.java
index 4702dee4e..4928079e8 100644
--- a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/jna/JnaUtils.java
+++ b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/jna/JnaUtils.java
@@ -1257,7 +1257,7 @@ public final class JnaUtils {
                     recoverShape(outShapeSize, outShapeNDim, outShapeData),
                     recoverShape(auxShapeSize, auxShapeNDim, auxShapeData));
         }
-        return null;
+        throw new IllegalArgumentException("Cannot infer shape based on the data provided!");
     }
 
     public static void loadLib(String path, boolean verbose) {
diff --git a/engines/mxnet/mxnet-model-zoo/README.md b/engines/mxnet/mxnet-model-zoo/README.md
index 395fce34e..9f7713a1c 100644
--- a/engines/mxnet/mxnet-model-zoo/README.md
+++ b/engines/mxnet/mxnet-model-zoo/README.md
@@ -27,7 +27,7 @@ You can pull the MXNet engine from the central Maven repository by including the
 <dependency>
     <groupId>ai.djl.mxnet</groupId>
     <artifactId>mxnet-model-zoo</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
 
diff --git a/engines/onnxruntime/onnxruntime-engine/README.md b/engines/onnxruntime/onnxruntime-engine/README.md
index 155db17f9..74b31d3e3 100644
--- a/engines/onnxruntime/onnxruntime-engine/README.md
+++ b/engines/onnxruntime/onnxruntime-engine/README.md
@@ -37,13 +37,13 @@ for the official ONNX Runtime project.
 ## Installation
 You can pull the ONNX Runtime engine from the central Maven repository by including the following dependency:
 
-- ai.djl.onnxruntime:onnxruntime-engine:0.15.0
+- ai.djl.onnxruntime:onnxruntime-engine:0.16.0
 
 ```xml
 <dependency>
     <groupId>ai.djl.onnxruntime</groupId>
     <artifactId>onnxruntime-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
@@ -61,7 +61,7 @@ Maven:
 <dependency>
     <groupId>ai.djl.onnxruntime</groupId>
     <artifactId>onnxruntime-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
     <exclusions>
         <exclusion>
@@ -80,7 +80,7 @@ Maven:
 
 Gradle:
 ```
-    implementation("ai.djl.onnxruntime:onnxruntime-engine:0.15.0") {
+    implementation("ai.djl.onnxruntime:onnxruntime-engine:0.16.0") {
         exclude group: "com.microsoft.onnxruntime", module: "onnxruntime"
     }
     implementation "com.microsoft.onnxruntime:onnxruntime_gpu:1.10.0"
diff --git a/engines/paddlepaddle/paddlepaddle-engine/README.md b/engines/paddlepaddle/paddlepaddle-engine/README.md
index 6da909601..e64ce2247 100644
--- a/engines/paddlepaddle/paddlepaddle-engine/README.md
+++ b/engines/paddlepaddle/paddlepaddle-engine/README.md
@@ -30,7 +30,7 @@ You can pull the PaddlePaddle engine from the central Maven repository by includ
 <dependency>
     <groupId>ai.djl.paddlepaddle</groupId>
     <artifactId>paddlepaddle-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
diff --git a/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpModel.java b/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpModel.java
index 409d679c3..82f3293bc 100644
--- a/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpModel.java
+++ b/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpModel.java
@@ -67,7 +67,7 @@ public class PpModel extends BaseModel {
     public void load(Path modelPath, String prefix, Map<String, ?> options) throws IOException {
         setModelDir(modelPath);
         String[] modelFiles = findModelFile(modelDir);
-        if (modelFiles == null) {
+        if (modelFiles.length == 0) {
             throw new FileNotFoundException("no __model__ or model file found in: " + modelDir);
         }
         long config = JniUtils.createConfig(modelFiles[0], modelFiles[1], device);
@@ -116,7 +116,7 @@ public class PpModel extends BaseModel {
                 return paths;
             }
         }
-        return null;
+        return new String[0];
     }
 
     /** {@inheritDoc} */
diff --git a/engines/paddlepaddle/paddlepaddle-model-zoo/README.md b/engines/paddlepaddle/paddlepaddle-model-zoo/README.md
index fc969b36b..ea078f4e8 100644
--- a/engines/paddlepaddle/paddlepaddle-model-zoo/README.md
+++ b/engines/paddlepaddle/paddlepaddle-model-zoo/README.md
@@ -26,7 +26,7 @@ from the central Maven repository by including the following dependency:
 <dependency>
     <groupId>ai.djl.paddlepaddle</groupId>
     <artifactId>paddlepaddle-model-zoo</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
 
diff --git a/engines/pytorch/pytorch-engine/README.md b/engines/pytorch/pytorch-engine/README.md
index b0f036e5e..f1fa8a325 100644
--- a/engines/pytorch/pytorch-engine/README.md
+++ b/engines/pytorch/pytorch-engine/README.md
@@ -24,13 +24,13 @@ The javadocs output is built in the `build/doc/javadoc` folder.
 ## Installation
 You can pull the PyTorch engine from the central Maven repository by including the following dependency:
 
-- ai.djl.pytorch:pytorch-engine:0.15.0
+- ai.djl.pytorch:pytorch-engine:0.16.0
 
 ```xml
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
@@ -45,6 +45,7 @@ The following table illustrates which pytorch version that DJL supports:
 
 | PyTorch engine version | PyTorch native library version             |
 |------------------------|--------------------------------------------|
+| pytorch-engine:0.16.0  | pytorch-native-auto: 1.8.1, 1.9.1, 1.10.0  |
 | pytorch-engine:0.15.0  | pytorch-native-auto: 1.8.1, 1.9.1, 1.10.0  |
 | pytorch-engine:0.14.0  | pytorch-native-auto: 1.8.1, 1.9.0, 1.9.1   |
 | pytorch-engine:0.13.0  | pytorch-native-auto:1.9.0                  |
@@ -68,7 +69,7 @@ You can choose a native library based on your platform if you don't have network
 ### macOS
 For macOS, you can use the following library:
 
-- ai.djl.pytorch:pytorch-jni:1.10.0-0.15.0
+- ai.djl.pytorch:pytorch-jni:1.10.0-0.16.0
 - ai.djl.pytorch:pytorch-native-cpu:1.10.0:osx-x86_64
 
 ```xml
@@ -82,7 +83,7 @@ For macOS, you can use the following library:
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-native-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
@@ -93,7 +94,7 @@ installed on your GPU machine, you can use one of the following library:
 
 #### Linux GPU
 
-- ai.djl.pytorch:pytorch-jni:1.10.0-0.15.0
+- ai.djl.pytorch:pytorch-jni:1.10.0-0.16.0
 - ai.djl.pytorch:pytorch-native-cu113:1.10.0:linux-x86_64 - CUDA 11.3
 - ai.djl.pytorch:pytorch-native-cu102:1.10.0:linux-x86_64 - CUDA 10.2
 
@@ -108,7 +109,7 @@ installed on your GPU machine, you can use one of the following library:
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
@@ -124,14 +125,14 @@ installed on your GPU machine, you can use one of the following library:
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
 
 ### Linux CPU
 
-- ai.djl.pytorch:pytorch-jni:1.10.0-0.15.0
+- ai.djl.pytorch:pytorch-jni:1.10.0-0.16.0
 - ai.djl.pytorch:pytorch-native-cpu:1.10.0:linux-x86_64
 
 ```xml
@@ -145,7 +146,7 @@ installed on your GPU machine, you can use one of the following library:
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
@@ -155,7 +156,7 @@ installed on your GPU machine, you can use one of the following library:
 We also provide packages for the system like CentOS 7/Ubuntu 14.04 with GLIBC >= 2.17.
 All the package were built with GCC 7, we provided a newer `libstdc++.so.6.24` in the package that contains `CXXABI_1.3.9` to use the package successfully.
 
-- ai.djl.pytorch:pytorch-jni:1.10.0-0.15.0
+- ai.djl.pytorch:pytorch-jni:1.10.0-0.16.0
 - ai.djl.pytorch:pytorch-native-cu113-precxx11:1.10.0:linux-x86_64 - CUDA 11.3
 - ai.djl.pytorch:pytorch-native-cpu-precxx11:1.10.0:linux-x86_64   - CPU
 
@@ -170,7 +171,7 @@ All the package were built with GCC 7, we provided a newer `libstdc++.so.6.24` i
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
@@ -186,7 +187,7 @@ All the package were built with GCC 7, we provided a newer `libstdc++.so.6.24` i
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
@@ -201,7 +202,7 @@ For the Windows platform, you can choose between CPU and GPU.
 
 #### Windows GPU
 
-- ai.djl.pytorch:pytorch-jni:1.10.0-0.15.0
+- ai.djl.pytorch:pytorch-jni:1.10.0-0.16.0
 - ai.djl.pytorch:pytorch-native-cu113:1.10.0:win-x86_64
 - ai.djl.pytorch:pytorch-native-cu102:1.10.0:win-x86_64
 
@@ -216,7 +217,7 @@ For the Windows platform, you can choose between CPU and GPU.
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
@@ -232,14 +233,14 @@ For the Windows platform, you can choose between CPU and GPU.
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
 
 ### Windows CPU
 
-- ai.djl.pytorch:pytorch-jni:1.10.0-0.15.0
+- ai.djl.pytorch:pytorch-jni:1.10.0-0.16.0
 - ai.djl.pytorch:pytorch-native-cpu:1.10.0:win-x86_64
 
 ```xml
@@ -253,7 +254,7 @@ For the Windows platform, you can choose between CPU and GPU.
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-jni</artifactId>
-    <version>1.10.0-0.15.0</version>
+    <version>1.10.0-0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
diff --git a/engines/pytorch/pytorch-model-zoo/README.md b/engines/pytorch/pytorch-model-zoo/README.md
index df25b3038..0f77dd3a5 100644
--- a/engines/pytorch/pytorch-model-zoo/README.md
+++ b/engines/pytorch/pytorch-model-zoo/README.md
@@ -25,7 +25,7 @@ You can pull the PyTorch engine from the central Maven repository by including t
 <dependency>
     <groupId>ai.djl.pytorch</groupId>
     <artifactId>pytorch-model-zoo</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
 
diff --git a/engines/pytorch/pytorch-native/build.gradle b/engines/pytorch/pytorch-native/build.gradle
index f92bf21e8..9c193fec0 100644
--- a/engines/pytorch/pytorch-native/build.gradle
+++ b/engines/pytorch/pytorch-native/build.gradle
@@ -12,6 +12,8 @@ if (project.hasProperty("pt_version") && project.property("pt_version") != "") {
 }
 boolean isRelease = project.hasProperty("release") || project.hasProperty("staging")
 boolean isPrecxx11 = project.hasProperty("precxx11")
+boolean isAarch64 = project.hasProperty("aarch64")
+
 String FLAVOR = "cpu"
 if (project.hasProperty("cu10")) {
     FLAVOR = "cu102"
@@ -26,15 +28,16 @@ String BINARY_ROOT = "${project.buildDir}/download"
 
 version = VERSION + (isRelease ? "" : "-SNAPSHOT")
 
-def downloadBuild(String ver, String os, String flavor, Boolean isPrecxx11 = false) {
+def downloadBuild(String ver, String os, String flavor, Boolean isPrecxx11 = false, Boolean isAarch64 = false) {
+    def arch = isAarch64 ? "aarch64" : "x86_64"
     exec {
         if (os == "win") {
             commandLine "${project.projectDir}/build.cmd", "${ver}", "${flavor}"
         } else {
             if (isPrecxx11) {
-                commandLine 'bash', 'build.sh', "${ver}", "${flavor}", "precxx11"
+                commandLine 'bash', 'build.sh', "${ver}", "${flavor}", "precxx11", "${arch}"
             } else {
-                commandLine 'bash', 'build.sh', "${ver}", "${flavor}"
+                commandLine 'bash', 'build.sh', "${ver}", "${flavor}", "cxx11", "${arch}"
             }
         }
     }
@@ -43,7 +46,7 @@ def downloadBuild(String ver, String os, String flavor, Boolean isPrecxx11 = fal
     // the reason why we duplicate the folder here is to insert djl_version into the path
     // so different versions of JNI wouldn't override each other. We don't also want publishDir
     // to have djl_version as engine would require to know that during the System.load()
-    String classifier = "${os}-x86_64"
+    String classifier = "${os}-${arch}"
     String ciDir = "${project.projectDir}/jnilib/${djl_version}/${classifier}/${flavor}"
     if (isPrecxx11) {
         ciDir = "${ciDir}-precxx11"
@@ -73,7 +76,8 @@ def downloadBuildAndroid(String ver) {
 }
 
 def prepareNativeLib(String binaryRoot, String ver) {
-    def url = "https://download.pytorch.org/libtorch"
+    def officialPytorchUrl = "https://download.pytorch.org/libtorch"
+    def aarch64PytorchUrl = "https://djl-ai.s3.amazonaws.com/publish/pytorch"
     String cu11
     if (ver.startsWith("1.8.") || ver.startsWith("1.9.")) {
         cu11 = "cu111"
@@ -92,7 +96,17 @@ def prepareNativeLib(String binaryRoot, String ver) {
             "cpu/libtorch-shared-with-deps-${ver}%2Bcpu.zip"                  : "cpu-precxx11/linux-x86_64",
             "${cu11}/libtorch-shared-with-deps-${ver}%2B${cu11}.zip"          : "${cu11}-precxx11/linux-x86_64"
     ]
-    files.each { entry ->
+
+    def aarch64Files = [
+            "${ver}/libtorch-cxx11-shared-with-deps-${ver}-aarch64.zip"       : "cpu/linux-aarch64"
+    ]
+
+    copyNativeLibToOutputDir(files, binaryRoot, officialPytorchUrl)
+    copyNativeLibToOutputDir(aarch64Files, binaryRoot, aarch64PytorchUrl)
+}
+
+def copyNativeLibToOutputDir(Map<String, String> fileStoreMap, String binaryRoot, String url) {
+    fileStoreMap.each { entry ->
         project.logger.lifecycle("Downloading ${url}/${entry.key}")
         def outputDir = new File("${binaryRoot}/${entry.value}")
         def file = new File("${outputDir}/libtorch.zip")
@@ -148,9 +162,9 @@ task compileJNI {
         if (System.properties['os.name'].toLowerCase(Locale.ROOT).contains("windows")) {
             downloadBuild("${VERSION}", "win", "${FLAVOR}")
         } else if (System.properties['os.name'].toLowerCase(Locale.ROOT).contains("mac")) {
-            downloadBuild("${VERSION}", "osx", "${FLAVOR}")
+            downloadBuild("${VERSION}", "osx", "${FLAVOR}", false, isAarch64)
         } else if (System.properties['os.name'].toLowerCase(Locale.ROOT).contains("linux")) {
-            downloadBuild("${VERSION}", "linux", "${FLAVOR}", isPrecxx11)
+            downloadBuild("${VERSION}", "linux", "${FLAVOR}", isPrecxx11, isAarch64)
         } else {
             throw new IllegalStateException("Unknown Architecture " + System.properties['os.name'] + "-${FLAVOR}")
         }
@@ -227,7 +241,7 @@ task downloadPyTorchNativeLib() {
 task uploadS3 {
     doLast {
         delete "${BINARY_ROOT}"
-        prepareNativeLib("${BINARY_ROOT}", "${version}")
+        prepareNativeLib("${BINARY_ROOT}", "${VERSION}")
 
         exec {
             commandLine "sh", "-c", "find ${BINARY_ROOT} -type f | xargs gzip"
@@ -242,7 +256,8 @@ task uploadS3 {
                 "${BINARY_ROOT}/cu102/win-x86_64/native/lib/",
                 "${BINARY_ROOT}/cu113/linux-x86_64/native/lib/",
                 "${BINARY_ROOT}/cu113/win-x86_64/native/lib/",
-                "${BINARY_ROOT}/cu113-precxx11/linux-x86_64/native/lib/"
+                "${BINARY_ROOT}/cu113-precxx11/linux-x86_64/native/lib/",
+                "${BINARY_ROOT}/cpu/linux-aarch64/native/lib"
         ]
         uploadDirs.each { item ->
             fileTree(item).files.name.each {
diff --git a/engines/pytorch/pytorch-native/build.sh b/engines/pytorch/pytorch-native/build.sh
index c03865e4e..af2cfe4e7 100755
--- a/engines/pytorch/pytorch-native/build.sh
+++ b/engines/pytorch/pytorch-native/build.sh
@@ -17,6 +17,7 @@ CXX11ABI="-cxx11-abi"
 if [[ $3 == "precxx11" ]]; then
   CXX11ABI=""
 fi
+ARCH=$4
 
 if [[ ! -d "libtorch" ]]; then
   if [[ $PLATFORM == 'linux' ]]; then
@@ -24,7 +25,13 @@ if [[ ! -d "libtorch" ]]; then
       echo "$FLAVOR is not supported."
       exit 1
     fi
-    curl -s https://download.pytorch.org/libtorch/${FLAVOR}/libtorch${CXX11ABI}-shared-with-deps-${VERSION}%2B${FLAVOR}.zip | jar xv
+
+    if [[ $ARCH == 'aarch64' ]]; then
+      curl -s https://djl-ai.s3.amazonaws.com/publish/pytorch/${VERSION}/libtorch-cxx11-shared-with-deps-${VERSION}-aarch64.zip | jar xv
+    else
+      curl -s https://download.pytorch.org/libtorch/${FLAVOR}/libtorch${CXX11ABI}-shared-with-deps-${VERSION}%2B${FLAVOR}.zip | jar xv
+    fi
+
   elif [[ $PLATFORM == 'darwin' ]]; then
     curl -s https://download.pytorch.org/libtorch/cpu/libtorch-macos-${VERSION}.zip | jar xv
   else
diff --git a/engines/tensorflow/tensorflow-api/README.md b/engines/tensorflow/tensorflow-api/README.md
index 10c696a2e..3bca85f54 100644
--- a/engines/tensorflow/tensorflow-api/README.md
+++ b/engines/tensorflow/tensorflow-api/README.md
@@ -16,6 +16,6 @@ You can pull the TensorFlow core java API from the central Maven repository by i
 <dependency>
     <groupId>ai.djl.tensorflow</groupId>
     <artifactId>tensorflow-api</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
diff --git a/engines/tensorflow/tensorflow-engine/README.md b/engines/tensorflow/tensorflow-engine/README.md
index ed0a69214..840a3e35d 100644
--- a/engines/tensorflow/tensorflow-engine/README.md
+++ b/engines/tensorflow/tensorflow-engine/README.md
@@ -28,13 +28,13 @@ The javadocs output is built in the `build/doc/javadoc` folder.
 
 You can pull the TensorFlow engine from the central Maven repository by including the following dependency:
 
-- ai.djl.tensorflow:tensorflow-engine:0.15.0
+- ai.djl.tensorflow:tensorflow-engine:0.16.0
 
 ```xml
 <dependency>
     <groupId>ai.djl.tensorflow</groupId>
     <artifactId>tensorflow-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
diff --git a/engines/tensorflow/tensorflow-model-zoo/README.md b/engines/tensorflow/tensorflow-model-zoo/README.md
index 88b412cd7..a949aa87c 100644
--- a/engines/tensorflow/tensorflow-model-zoo/README.md
+++ b/engines/tensorflow/tensorflow-model-zoo/README.md
@@ -26,7 +26,7 @@ from the central Maven repository by including the following dependency:
 <dependency>
     <groupId>ai.djl.tensorflow</groupId>
     <artifactId>tensorflow-model-zoo</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
 
diff --git a/engines/tensorrt/README.md b/engines/tensorrt/README.md
index fe33a7e9c..40a68f885 100644
--- a/engines/tensorrt/README.md
+++ b/engines/tensorrt/README.md
@@ -28,13 +28,13 @@ The javadocs output is generated in the `build/doc/javadoc` folder.
 ## Installation
 You can pull the TensorRT engine from the central Maven repository by including the following dependency:
 
-- ai.djl.tensorrt:tensorrt:0.15.0
+- ai.djl.tensorrt:tensorrt:0.16.0
 
 ```xml
 <dependency>
     <groupId>ai.djl.tensorrt</groupId>
     <artifactId>tensorrt</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
diff --git a/engines/tflite/tflite-engine/README.md b/engines/tflite/tflite-engine/README.md
index f0befe2f9..a9de9d350 100644
--- a/engines/tflite/tflite-engine/README.md
+++ b/engines/tflite/tflite-engine/README.md
@@ -24,13 +24,13 @@ The javadocs output is built in the `build/doc/javadoc` folder.
 ## Installation
 You can pull the TensorFlow Lite engine from the central Maven repository by including the following dependency:
 
-- ai.djl.tflite:tflite-engine:0.15.0
+- ai.djl.tflite:tflite-engine:0.16.0
 
 ```xml
 <dependency>
     <groupId>ai.djl.tflite</groupId>
     <artifactId>tflite-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
     <scope>runtime</scope>
 </dependency>
 ```
diff --git a/examples/pom.xml b/examples/pom.xml
index 4dd630bce..432b57e20 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -5,12 +5,12 @@
 
     <groupId>ai.djl</groupId>
     <artifactId>examples</artifactId>
-    <version>0.16.0-SNAPSHOT</version>
+    <version>0.17.0-SNAPSHOT</version>
 
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <djl.version>0.16.0-SNAPSHOT</djl.version>
+        <djl.version>0.17.0-SNAPSHOT</djl.version>
         <exec.mainClass>ai.djl.examples.inference.ObjectDetection</exec.mainClass>
     </properties>
 
diff --git a/examples/src/main/java/ai/djl/examples/training/transferlearning/TrainAmazonReviewRanking.java b/examples/src/main/java/ai/djl/examples/training/transferlearning/TrainAmazonReviewRanking.java
index 1db9470c4..c2ef09933 100644
--- a/examples/src/main/java/ai/djl/examples/training/transferlearning/TrainAmazonReviewRanking.java
+++ b/examples/src/main/java/ai/djl/examples/training/transferlearning/TrainAmazonReviewRanking.java
@@ -124,7 +124,7 @@ public final class TrainAmazonReviewRanking {
         float paddingToken = tokenizer.getVocabulary().getIndex("[PAD]");
         return CsvDataset.builder()
                 .optCsvUrl(amazonReview)
-                .setCsvFormat(CSVFormat.TDF.withQuote(null).withHeader())
+                .setCsvFormat(CSVFormat.TDF.builder().setQuote(null).setHeader().build())
                 .setSampling(arguments.getBatchSize(), true)
                 .addFeature(
                         new CsvDataset.Feature(
diff --git a/extensions/aws-ai/README.md b/extensions/aws-ai/README.md
index 71aa1f0e7..3493c6848 100644
--- a/extensions/aws-ai/README.md
+++ b/extensions/aws-ai/README.md
@@ -58,6 +58,6 @@ You can pull the module from the central Maven repository by including the follo
 <dependency>
     <groupId>ai.djl.aws</groupId>
     <artifactId>aws-ai</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
diff --git a/extensions/benchmark/README.md b/extensions/benchmark/README.md
index dd1714a50..4fcb70a0f 100644
--- a/extensions/benchmark/README.md
+++ b/extensions/benchmark/README.md
@@ -48,25 +48,25 @@ sudo snap alias djlbench djl-bench
 - Or download .deb package from S3
 
 ```
-curl -O https://publish.djl.ai/djl-bench/0.15.0/djl-bench_0.15.0-1_all.deb
-sudo dpkg -i djl-bench_0.15.0-1_all.deb
+curl -O https://publish.djl.ai/djl-bench/0.16.0/djl-bench_0.16.0-1_all.deb
+sudo dpkg -i djl-bench_0.16.0-1_all.deb
 ```
 
 For centOS or Amazon Linux 2
 
-You can download djl-bench zip file from [here](https://publish.djl.ai/djl-bench/0.15.0/benchmark-0.15.0.zip).
+You can download djl-bench zip file from [here](https://publish.djl.ai/djl-bench/0.16.0/benchmark-0.16.0.zip).
 
 ```
-curl -O https://publish.djl.ai/djl-bench/0.15.0/benchmark-0.15.0.zip
-unzip benchmark-0.15.0.zip
-rm benchmark-0.15.0.zip
-sudo ln -s $PWD/benchmark-0.15.0/bin/benchmark /usr/bin/djl-bench
+curl -O https://publish.djl.ai/djl-bench/0.16.0/benchmark-0.16.0.zip
+unzip benchmark-0.16.0.zip
+rm benchmark-0.16.0.zip
+sudo ln -s $PWD/benchmark-0.16.0/bin/benchmark /usr/bin/djl-bench
 ```
 
 For Windows
 
 We are considering to create a `chocolatey` package for Windows. For the time being, you can
-download djl-bench zip file from [here](https://publish.djl.ai/djl-bench/0.15.0/benchmark-0.15.0.zip).
+download djl-bench zip file from [here](https://publish.djl.ai/djl-bench/0.16.0/benchmark-0.16.0.zip).
 
 Or you can run benchmark using gradle:
 
diff --git a/extensions/benchmark/snapcraft/snapcraft.yaml b/extensions/benchmark/snapcraft/snapcraft.yaml
index b6409f090..b4b6a691d 100644
--- a/extensions/benchmark/snapcraft/snapcraft.yaml
+++ b/extensions/benchmark/snapcraft/snapcraft.yaml
@@ -1,5 +1,5 @@
 name: djlbench
-version: '0.15.0'
+version: '0.16.0'
 title: DJL Benhmark
 license: Apache-2.0
 summary: A machine learning benchmarking toolkit
diff --git a/extensions/fasttext/README.md b/extensions/fasttext/README.md
index f39e64b57..9063c64b5 100644
--- a/extensions/fasttext/README.md
+++ b/extensions/fasttext/README.md
@@ -34,7 +34,7 @@ You can pull the fastText engine from the central Maven repository by including
 <dependency>
     <groupId>ai.djl.fasttext</groupId>
     <artifactId>fasttext-engine</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
 
diff --git a/extensions/fasttext/src/main/java/ai/djl/fasttext/FtModel.java b/extensions/fasttext/src/main/java/ai/djl/fasttext/FtModel.java
index d7b4451b7..70fa17c53 100644
--- a/extensions/fasttext/src/main/java/ai/djl/fasttext/FtModel.java
+++ b/extensions/fasttext/src/main/java/ai/djl/fasttext/FtModel.java
@@ -214,7 +214,7 @@ public class FtModel implements Model {
     /** {@inheritDoc} */
     @Override
     public String[] getArtifactNames() {
-        return null;
+        return new String[0];
     }
 
     /** {@inheritDoc} */
diff --git a/extensions/fasttext/src/main/java/ai/djl/fasttext/FtTrainingConfig.java b/extensions/fasttext/src/main/java/ai/djl/fasttext/FtTrainingConfig.java
index e2d30044b..b6e39a117 100644
--- a/extensions/fasttext/src/main/java/ai/djl/fasttext/FtTrainingConfig.java
+++ b/extensions/fasttext/src/main/java/ai/djl/fasttext/FtTrainingConfig.java
@@ -23,6 +23,7 @@ import ai.djl.training.optimizer.Optimizer;
 import ai.djl.util.PairList;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
 import java.util.function.Predicate;
@@ -276,13 +277,13 @@ public class FtTrainingConfig implements TrainingConfig {
     /** {@inheritDoc} */
     @Override
     public List<Evaluator> getEvaluators() {
-        return null;
+        return Collections.emptyList();
     }
 
     /** {@inheritDoc} */
     @Override
     public List<TrainingListener> getTrainingListeners() {
-        return null;
+        return Collections.emptyList();
     }
 
     /**
diff --git a/extensions/hadoop/README.md b/extensions/hadoop/README.md
index 9a4d71106..f5a562684 100644
--- a/extensions/hadoop/README.md
+++ b/extensions/hadoop/README.md
@@ -52,6 +52,6 @@ You can pull the module from the central Maven repository by including the follo
 <dependency>
     <groupId>ai.djl.hadoop</groupId>
     <artifactId>hadoop</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
diff --git a/extensions/opencv/README.md b/extensions/opencv/README.md
index ec8fc3f1c..f296bd0ba 100644
--- a/extensions/opencv/README.md
+++ b/extensions/opencv/README.md
@@ -21,6 +21,6 @@ You can pull the module from the central Maven repository by including the follo
 <dependency>
     <groupId>ai.djl.opencv</groupId>
     <artifactId>opencv</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
diff --git a/extensions/sentencepiece/README.md b/extensions/sentencepiece/README.md
index 6af8f106e..099864cb4 100644
--- a/extensions/sentencepiece/README.md
+++ b/extensions/sentencepiece/README.md
@@ -21,6 +21,6 @@ You can pull the module from the central Maven repository by including the follo
 <dependency>
     <groupId>ai.djl.sentencepiece</groupId>
     <artifactId>sentencepiece</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
diff --git a/extensions/tokenizers/README.md b/extensions/tokenizers/README.md
index 66b1f2961..33846eaca 100644
--- a/extensions/tokenizers/README.md
+++ b/extensions/tokenizers/README.md
@@ -21,6 +21,6 @@ You can pull the module from the central Maven repository by including the follo
 <dependency>
     <groupId>ai.djl.huggingface</groupId>
     <artifactId>tokenizers</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
diff --git a/gradle.properties b/gradle.properties
index 8d3a72ac3..e5805ecb5 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -7,9 +7,9 @@ systemProp.org.gradle.internal.http.connectionTimeout=60000
 # FIXME: Workaround gradle publish issue: https://github.com/gradle/gradle/issues/11308
 systemProp.org.gradle.internal.publish.checksums.insecure=true
 
-djl_version=0.16.0
+djl_version=0.17.0
 mxnet_version=1.9.0
-pytorch_version=1.10.0
+pytorch_version=1.10.2
 tensorflow_version=2.7.0
 tflite_version=2.6.2
 dlr_version=1.6.0
@@ -21,19 +21,19 @@ tokenizers_version=0.11.0
 fasttext_version=0.9.2
 xgboost_version=1.4.1
 
-commons_cli_version=1.4
+commons_cli_version=1.5.0
 commons_compress_version=1.21
-commons_csv_version=1.8
+commons_csv_version=1.9.0
 commons_logging_version=1.2
-gson_version=2.8.9
-jna_version=5.9.0
-slf4j_version=1.7.32
-log4j_slf4j_version=2.17.1
-awssdk_version=2.17.109
+gson_version=2.9.0
+jna_version=5.10.0
+slf4j_version=1.7.36
+log4j_slf4j_version=2.17.2
+awssdk_version=2.17.151
 hadoop_version=3.3.1
 javacpp_version=1.5.6
 protobuf_version=3.19.2
 
-antlr_version=4.9.2
+antlr_version=4.9.3
 testng_version=7.5
 junit_version=4.13.2
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c009a44b1..f1ffe6612 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
diff --git a/jupyter/BERTQA.ipynb b/jupyter/BERTQA.ipynb
index 1fa18c265..7b7dcd9db 100644
--- a/jupyter/BERTQA.ipynb
+++ b/jupyter/BERTQA.ipynb
@@ -46,11 +46,11 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-engine:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-model-zoo:0.15.0\n",
-    "%maven ai.djl.pytorch:pytorch-engine:0.15.0\n",
-    "%maven ai.djl.pytorch:pytorch-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-engine:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-model-zoo:0.16.0\n",
+    "%maven ai.djl.pytorch:pytorch-engine:0.16.0\n",
+    "%maven ai.djl.pytorch:pytorch-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
diff --git a/jupyter/load_mxnet_model.ipynb b/jupyter/load_mxnet_model.ipynb
index 977e0ad4f..4a73ee6e9 100644
--- a/jupyter/load_mxnet_model.ipynb
+++ b/jupyter/load_mxnet_model.ipynb
@@ -22,10 +22,10 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl:model-zoo:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-engine:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl:model-zoo:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-engine:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
diff --git a/jupyter/load_pytorch_model.ipynb b/jupyter/load_pytorch_model.ipynb
index 039ef811e..7fbe6df1e 100644
--- a/jupyter/load_pytorch_model.ipynb
+++ b/jupyter/load_pytorch_model.ipynb
@@ -25,8 +25,8 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.pytorch:pytorch-engine:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.pytorch:pytorch-engine:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
@@ -106,7 +106,7 @@
     "...\n",
     "```\n",
     "\n",
-    "Then, we will use this pipeline to create the [`Translator`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/translate/Translator.html)"
+    "Then, we will use this pipeline to create the [`Translator`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/translate/Translator.html)"
    ]
   },
   {
diff --git a/jupyter/mxnet/load_your_own_mxnet_bert.ipynb b/jupyter/mxnet/load_your_own_mxnet_bert.ipynb
index da8238356..2031e18bd 100644
--- a/jupyter/mxnet/load_your_own_mxnet_bert.ipynb
+++ b/jupyter/mxnet/load_your_own_mxnet_bert.ipynb
@@ -41,9 +41,9 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-engine:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-engine:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
@@ -310,7 +310,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Armed with the needed knowledge, you can write an implementation of the `Translator` interface. `BertTranslator` uses the code snippets explained previously to implement the `processInput`method. For more information, see [`NDManager`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/ndarray/NDManager.html).\n",
+    "Armed with the needed knowledge, you can write an implementation of the `Translator` interface. `BertTranslator` uses the code snippets explained previously to implement the `processInput`method. For more information, see [`NDManager`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/ndarray/NDManager.html).\n",
     "\n",
     "```\n",
     "manager.create(Number[] data, Shape)\n",
@@ -389,7 +389,7 @@
    "source": [
     "Congrats! You have created your first Translator! We have pre-filled the `processOutput()` function to process the `NDList` and return it in a desired format. `processInput()` and `processOutput()` offer the flexibility to get the predictions from the model in any format you desire. \n",
     "\n",
-    "With the Translator implemented, you need to bring up the predictor that uses your `Translator` to start making predictions. You can find the usage for `Predictor` in the [Predictor Javadoc](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/inference/Predictor.html). Create a translator and use the `question` and `resourceDocument` provided previously."
+    "With the Translator implemented, you need to bring up the predictor that uses your `Translator` to start making predictions. You can find the usage for `Predictor` in the [Predictor Javadoc](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/inference/Predictor.html). Create a translator and use the `question` and `resourceDocument` provided previously."
    ]
   },
   {
diff --git a/jupyter/object_detection_with_model_zoo.ipynb b/jupyter/object_detection_with_model_zoo.ipynb
index 3d0aea456..6e0b718c6 100644
--- a/jupyter/object_detection_with_model_zoo.ipynb
+++ b/jupyter/object_detection_with_model_zoo.ipynb
@@ -21,9 +21,9 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-engine:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-engine:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
diff --git a/jupyter/onnxruntime/machine_learning_with_ONNXRuntime.ipynb b/jupyter/onnxruntime/machine_learning_with_ONNXRuntime.ipynb
index ce81fd9ea..9e77ac6fa 100644
--- a/jupyter/onnxruntime/machine_learning_with_ONNXRuntime.ipynb
+++ b/jupyter/onnxruntime/machine_learning_with_ONNXRuntime.ipynb
@@ -54,8 +54,8 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.onnxruntime:onnxruntime-engine:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.onnxruntime:onnxruntime-engine:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
diff --git a/jupyter/paddlepaddle/face_mask_detection_paddlepaddle.ipynb b/jupyter/paddlepaddle/face_mask_detection_paddlepaddle.ipynb
index 04b5dabcb..a5c778d9c 100644
--- a/jupyter/paddlepaddle/face_mask_detection_paddlepaddle.ipynb
+++ b/jupyter/paddlepaddle/face_mask_detection_paddlepaddle.ipynb
@@ -26,12 +26,12 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32\n",
     "\n",
     "// second engine to do preprocessing and postprocessing\n",
-    "%maven ai.djl.pytorch:pytorch-engine:0.15.0"
+    "%maven ai.djl.pytorch:pytorch-engine:0.16.0"
    ]
   },
   {
diff --git a/jupyter/paddlepaddle/face_mask_detection_paddlepaddle_zh.ipynb b/jupyter/paddlepaddle/face_mask_detection_paddlepaddle_zh.ipynb
index c1625ab40..4afd631e7 100644
--- a/jupyter/paddlepaddle/face_mask_detection_paddlepaddle_zh.ipynb
+++ b/jupyter/paddlepaddle/face_mask_detection_paddlepaddle_zh.ipynb
@@ -24,12 +24,12 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32\n",
     "\n",
     "// second engine to do preprocessing and postprocessing\n",
-    "%maven ai.djl.pytorch:pytorch-engine:0.15.0"
+    "%maven ai.djl.pytorch:pytorch-engine:0.16.0"
    ]
   },
   {
diff --git a/jupyter/paddlepaddle/paddle_ocr_java.ipynb b/jupyter/paddlepaddle/paddle_ocr_java.ipynb
index b62c6d212..c75842eb6 100644
--- a/jupyter/paddlepaddle/paddle_ocr_java.ipynb
+++ b/jupyter/paddlepaddle/paddle_ocr_java.ipynb
@@ -25,12 +25,12 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32\n",
     "\n",
     "// second engine to do preprocessing and postprocessing\n",
-    "%maven ai.djl.pytorch:pytorch-engine:0.15.0"
+    "%maven ai.djl.pytorch:pytorch-engine:0.16.0"
    ]
   },
   {
diff --git a/jupyter/paddlepaddle/paddle_ocr_java_zh.ipynb b/jupyter/paddlepaddle/paddle_ocr_java_zh.ipynb
index de9ab6d2a..aca169821 100644
--- a/jupyter/paddlepaddle/paddle_ocr_java_zh.ipynb
+++ b/jupyter/paddlepaddle/paddle_ocr_java_zh.ipynb
@@ -23,12 +23,12 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32\n",
     "\n",
     "// second engine to do preprocessing and postprocessing\n",
-    "%maven ai.djl.pytorch:pytorch-engine:0.15.0"
+    "%maven ai.djl.pytorch:pytorch-engine:0.16.0"
    ]
   },
   {
diff --git a/jupyter/pytorch/load_your_own_pytorch_bert.ipynb b/jupyter/pytorch/load_your_own_pytorch_bert.ipynb
index a67d60f09..923f0d986 100644
--- a/jupyter/pytorch/load_your_own_pytorch_bert.ipynb
+++ b/jupyter/pytorch/load_your_own_pytorch_bert.ipynb
@@ -41,9 +41,9 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.pytorch:pytorch-engine:0.15.0\n",
-    "%maven ai.djl.pytorch:pytorch-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.pytorch:pytorch-engine:0.16.0\n",
+    "%maven ai.djl.pytorch:pytorch-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32\n",
     "%maven net.java.dev.jna:jna:5.8.0"
    ]
@@ -273,7 +273,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Armed with the needed knowledge, you can write an implementation of the `Translator` interface. `BertTranslator` uses the code snippets explained previously to implement the `processInput`method. For more information, see [`NDManager`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/ndarray/NDManager.html).\n",
+    "Armed with the needed knowledge, you can write an implementation of the `Translator` interface. `BertTranslator` uses the code snippets explained previously to implement the `processInput`method. For more information, see [`NDManager`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/ndarray/NDManager.html).\n",
     "\n",
     "```\n",
     "manager.create(Number[] data, Shape)\n",
@@ -346,7 +346,7 @@
    "source": [
     "Congrats! You have created your first Translator! We have pre-filled the `processOutput()` function to process the `NDList` and return it in a desired format. `processInput()` and `processOutput()` offer the flexibility to get the predictions from the model in any format you desire. \n",
     "\n",
-    "With the Translator implemented, you need to bring up the predictor that uses your `Translator` to start making predictions. You can find the usage for `Predictor` in the [Predictor Javadoc](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/inference/Predictor.html). Create a translator and use the `question` and `resourceDocument` provided previously."
+    "With the Translator implemented, you need to bring up the predictor that uses your `Translator` to start making predictions. You can find the usage for `Predictor` in the [Predictor Javadoc](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/inference/Predictor.html). Create a translator and use the `question` and `resourceDocument` provided previously."
    ]
   },
   {
diff --git a/jupyter/rank_classification_using_BERT_on_Amazon_Review.ipynb b/jupyter/rank_classification_using_BERT_on_Amazon_Review.ipynb
index 18dad6ef4..b8d50006c 100644
--- a/jupyter/rank_classification_using_BERT_on_Amazon_Review.ipynb
+++ b/jupyter/rank_classification_using_BERT_on_Amazon_Review.ipynb
@@ -38,13 +38,13 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl:basicdataset:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl:basicdataset:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32\n",
-    "%maven ai.djl.mxnet:mxnet-model-zoo:0.15.0\n",
+    "%maven ai.djl.mxnet:mxnet-model-zoo:0.16.0\n",
     "\n",
     "// PyTorch\n",
-    "// %maven ai.djl.pytorch:pytorch-model-zoo:0.15.0"
+    "// %maven ai.djl.pytorch:pytorch-model-zoo:0.16.0"
    ]
   },
   {
diff --git a/jupyter/tensorflow/pneumonia_detection.ipynb b/jupyter/tensorflow/pneumonia_detection.ipynb
index 765ee896a..d8bdbdb8c 100644
--- a/jupyter/tensorflow/pneumonia_detection.ipynb
+++ b/jupyter/tensorflow/pneumonia_detection.ipynb
@@ -36,10 +36,10 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.tensorflow:tensorflow-api:0.15.0\n",
-    "%maven ai.djl.tensorflow:tensorflow-engine:0.15.0\n",
-    "%maven ai.djl.tensorflow:tensorflow-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.tensorflow:tensorflow-api:0.16.0\n",
+    "%maven ai.djl.tensorflow:tensorflow-engine:0.16.0\n",
+    "%maven ai.djl.tensorflow:tensorflow-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
diff --git a/jupyter/tensorflow/rank_classification_using_BERT_on_Amazon_Review.ipynb b/jupyter/tensorflow/rank_classification_using_BERT_on_Amazon_Review.ipynb
index 926f63d1a..e1fcfe601 100644
--- a/jupyter/tensorflow/rank_classification_using_BERT_on_Amazon_Review.ipynb
+++ b/jupyter/tensorflow/rank_classification_using_BERT_on_Amazon_Review.ipynb
@@ -36,9 +36,9 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl.tensorflow:tensorflow-engine:0.15.0\n",
-    "%maven ai.djl.tensorflow:tensorflow-api:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl.tensorflow:tensorflow-engine:0.16.0\n",
+    "%maven ai.djl.tensorflow:tensorflow-api:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
diff --git a/jupyter/tensorflow_lite/inference_with_tensorflow_lite.ipynb b/jupyter/tensorflow_lite/inference_with_tensorflow_lite.ipynb
index 80697f629..c09fc0bf4 100644
--- a/jupyter/tensorflow_lite/inference_with_tensorflow_lite.ipynb
+++ b/jupyter/tensorflow_lite/inference_with_tensorflow_lite.ipynb
@@ -22,13 +22,13 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl:model-zoo:0.15.0\n",
-    "%maven ai.djl.tflite:tflite-engine:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl:model-zoo:0.16.0\n",
+    "%maven ai.djl.tflite:tflite-engine:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32\n",
     "\n",
     "// Use secondary engine to help pre-processing and post-processing\n",
-    "%maven ai.djl.pytorch:pytorch-engine:0.15.0"
+    "%maven ai.djl.pytorch:pytorch-engine:0.16.0"
    ]
   },
   {
diff --git a/jupyter/transfer_learning_on_cifar10.ipynb b/jupyter/transfer_learning_on_cifar10.ipynb
index 0aedeba1d..dfbc409a9 100644
--- a/jupyter/transfer_learning_on_cifar10.ipynb
+++ b/jupyter/transfer_learning_on_cifar10.ipynb
@@ -35,10 +35,10 @@
    "source": [
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl:basicdataset:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-engine:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl:basicdataset:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-engine:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
diff --git a/jupyter/tutorial/01_create_your_first_network.ipynb b/jupyter/tutorial/01_create_your_first_network.ipynb
index c7b67a862..35949f26d 100644
--- a/jupyter/tutorial/01_create_your_first_network.ipynb
+++ b/jupyter/tutorial/01_create_your_first_network.ipynb
@@ -27,7 +27,7 @@
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
     "// Add the maven dependencies\n",
-    "%maven ai.djl:api:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
@@ -53,7 +53,7 @@
     "\n",
     "## Application\n",
     "\n",
-    "The first thing to figure out when trying to build a neural network, like building most functions, is what your function signature is. What are your input types and output types? Because most models use relatively consistent signatures, we refer to them as [Applications](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/Application.html). Within the Applications interface, you can find a list of some of the more common model applications used in deep learning.\n",
+    "The first thing to figure out when trying to build a neural network, like building most functions, is what your function signature is. What are your input types and output types? Because most models use relatively consistent signatures, we refer to them as [Applications](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/Application.html). Within the Applications interface, you can find a list of some of the more common model applications used in deep learning.\n",
     "\n",
     "In this tutorial, we will focus on the image classification application. It is one of the most common first applications and has a significant history with deep learning. In image classification, the input is a single image and it is classified based on the main subject of the image into a number of different possible classes. The classes for the image depend on the specific data you are training with."
    ]
@@ -83,7 +83,7 @@
     "\n",
     "![Mnist Image](https://upload.wikimedia.org/wikipedia/commons/2/27/MnistExamples.png)\n",
     "\n",
-    "Once you understand your dataset, you should create an implementation of the [Dataset class](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/dataset/Dataset.html). In this case, we provide the MNIST dataset built-in to make it easy for you to use it.\n",
+    "Once you understand your dataset, you should create an implementation of the [Dataset class](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/dataset/Dataset.html). In this case, we provide the MNIST dataset built-in to make it easy for you to use it.\n",
     "\n",
     "## Multilayer Perceptron\n",
     "\n",
@@ -123,16 +123,16 @@
     "\n",
     "### NDArray\n",
     "\n",
-    "The core data type used for working with deep learning is the [NDArray](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/ndarray/NDArray.html). An NDArray represents a multidimensional, fixed-size homogeneous array. It has very similar behavior to the Numpy python package with the addition of efficient computing. We also have a helper class, the [NDList](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/ndarray/NDList.html) which is a list of NDArrays which can have different sizes and data types.\n",
+    "The core data type used for working with deep learning is the [NDArray](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/ndarray/NDArray.html). An NDArray represents a multidimensional, fixed-size homogeneous array. It has very similar behavior to the Numpy python package with the addition of efficient computing. We also have a helper class, the [NDList](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/ndarray/NDList.html) which is a list of NDArrays which can have different sizes and data types.\n",
     "\n",
     "### Block API\n",
     "\n",
-    "In DJL, [Blocks](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/nn/Block.html) serve a purpose similar to functions that convert an input `NDList` to an output `NDList`. They can represent single operations, parts of a neural network, and even the whole neural network. What makes blocks special is that they contain a number of parameters that are used in their function and are trained during deep learning. As these parameters are trained, the function represented by the blocks get more and more accurate.\n",
+    "In DJL, [Blocks](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/nn/Block.html) serve a purpose similar to functions that convert an input `NDList` to an output `NDList`. They can represent single operations, parts of a neural network, and even the whole neural network. What makes blocks special is that they contain a number of parameters that are used in their function and are trained during deep learning. As these parameters are trained, the function represented by the blocks get more and more accurate.\n",
     "\n",
     "When building these block functions, the easiest way is to use composition. Similar to how functions are built by calling other functions, blocks can be built by combining other blocks. We refer to the containing block as the parent and the sub-blocks as the children.\n",
     "\n",
     "\n",
-    "We provide several helpers to make it easy to build common block composition structures. For the MLP we will use the [SequentialBlock](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/nn/SequentialBlock.html), a container block whose children form a chain of blocks where each child block feeds its output to the next child block in a sequence.\n",
+    "We provide several helpers to make it easy to build common block composition structures. For the MLP we will use the [SequentialBlock](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/nn/SequentialBlock.html), a container block whose children form a chain of blocks where each child block feeds its output to the next child block in a sequence.\n",
     " "
    ]
   },
@@ -151,7 +151,7 @@
    "source": [
     "## Step 4: Add blocks to SequentialBlock\n",
     "\n",
-    "An MLP is organized into several layers. Each layer is composed of a [Linear Block](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/nn/core/Linear.html) and a non-linear activation function. If we just had two linear blocks in a row, it would be the same as a combined linear block ($f(x) = W_2(W_1x) = (W_2W_1)x = W_{combined}x$). An activation is used to intersperse between the linear blocks to allow them to represent non-linear functions. We will use the popular [ReLU](https://javadoc.io/static/ai.djl/api/0.15.0/ai/djl/nn/Activation.html#reluBlock--) as our activation function.\n",
+    "An MLP is organized into several layers. Each layer is composed of a [Linear Block](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/nn/core/Linear.html) and a non-linear activation function. If we just had two linear blocks in a row, it would be the same as a combined linear block ($f(x) = W_2(W_1x) = (W_2W_1)x = W_{combined}x$). An activation is used to intersperse between the linear blocks to allow them to represent non-linear functions. We will use the popular [ReLU](https://javadoc.io/static/ai.djl/api/0.16.0/ai/djl/nn/Activation.html#reluBlock--) as our activation function.\n",
     "\n",
     "The first layer and last layers have fixed sizes depending on your desired input and output size. However, you are free to choose the number and sizes of the middle layers in the network. We will create a smaller MLP with two middle layers that gradually decrease the size. Typically, you would experiment with different values to see what works the best on your data set."
    ]
diff --git a/jupyter/tutorial/02_train_your_first_model.ipynb b/jupyter/tutorial/02_train_your_first_model.ipynb
index ba00115b7..e4e82509e 100644
--- a/jupyter/tutorial/02_train_your_first_model.ipynb
+++ b/jupyter/tutorial/02_train_your_first_model.ipynb
@@ -23,10 +23,10 @@
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
     "// Add the maven dependencies\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl:basicdataset:0.15.0\n",
-    "%maven ai.djl:model-zoo:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-engine:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl:basicdataset:0.16.0\n",
+    "%maven ai.djl:model-zoo:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-engine:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
@@ -59,13 +59,13 @@
    "source": [
     "# Step 1: Prepare MNIST dataset for training\n",
     "\n",
-    "In order to train, you must create a [Dataset class](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/dataset/Dataset.html) to contain your training data. A dataset is a collection of sample input/output pairs for the function represented by your neural network. Each single input/output is represented by a [Record](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/dataset/Record.html). Each record could have multiple arrays of inputs or outputs such as an image question and answer dataset where the input is both an image and a question about the image while the output is the answer to the question.\n",
+    "In order to train, you must create a [Dataset class](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/dataset/Dataset.html) to contain your training data. A dataset is a collection of sample input/output pairs for the function represented by your neural network. Each single input/output is represented by a [Record](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/dataset/Record.html). Each record could have multiple arrays of inputs or outputs such as an image question and answer dataset where the input is both an image and a question about the image while the output is the answer to the question.\n",
     "\n",
-    "Because data learning is highly parallelizable, training is often done not with a single record at a time, but a [Batch](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/dataset/Batch.html). This can lead to significant performance gains, especially when working with images\n",
+    "Because data learning is highly parallelizable, training is often done not with a single record at a time, but a [Batch](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/dataset/Batch.html). This can lead to significant performance gains, especially when working with images\n",
     "\n",
     "## Sampler\n",
     "\n",
-    "Then, we must decide the parameters for loading data from the dataset. The only parameter we need for MNIST is the choice of [Sampler](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/dataset/Sampler.html). The sampler decides which and how many element from datasets are part of each batch when iterating through it. We will have it randomly shuffle the elements for the batch and use a batchSize of 32. The batchSize is usually the largest power of 2 that fits within memory."
+    "Then, we must decide the parameters for loading data from the dataset. The only parameter we need for MNIST is the choice of [Sampler](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/dataset/Sampler.html). The sampler decides which and how many element from datasets are part of each batch when iterating through it. We will have it randomly shuffle the elements for the batch and use a batchSize of 32. The batchSize is usually the largest power of 2 that fits within memory."
    ]
   },
   {
@@ -85,7 +85,7 @@
    "source": [
     "# Step 2: Create your Model\n",
     "\n",
-    "Next we will build a model. A [Model](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/Model.html) contains a neural network [Block](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/nn/Block.html) along with additional artifacts used for the training process. It possesses additional information about the inputs, outputs, shapes, and data types you will use. Generally, you will use the Model once you have fully completed your Block.\n",
+    "Next we will build a model. A [Model](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/Model.html) contains a neural network [Block](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/nn/Block.html) along with additional artifacts used for the training process. It possesses additional information about the inputs, outputs, shapes, and data types you will use. Generally, you will use the Model once you have fully completed your Block.\n",
     "\n",
     "In this part of the tutorial, we will use the built-in Multilayer Perceptron Block from the Model Zoo. To learn how to build it from scratch, see the previous tutorial: [Create Your First Network](01_create_your_first_network.ipynb).\n",
     "\n",
@@ -108,21 +108,21 @@
    "source": [
     "# Step 3: Create a Trainer\n",
     "\n",
-    "Now, you can create a [`Trainer`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/Trainer.html) to train your model. The trainer is the main class to orchestrate the training process. Usually, they will be opened using a try-with-resources and closed after training is over.\n",
+    "Now, you can create a [`Trainer`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/Trainer.html) to train your model. The trainer is the main class to orchestrate the training process. Usually, they will be opened using a try-with-resources and closed after training is over.\n",
     "\n",
     "The trainer takes an existing model and attempts to optimize the parameters inside the model's Block to best match the dataset. Most optimization is based upon [Stochastic Gradient Descent](https://en.wikipedia.org/wiki/Stochastic_gradient_descent) (SGD).\n",
     "\n",
     "## Step 3.1: Setup your training configurations\n",
     "\n",
-    "Before you create your trainer, we we will need a [training configuration](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/DefaultTrainingConfig.html) that describes how to train your model.\n",
+    "Before you create your trainer, we we will need a [training configuration](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/DefaultTrainingConfig.html) that describes how to train your model.\n",
     "\n",
     "The following are a few common items you may need to configure your training:\n",
     "\n",
-    "* **REQUIRED** [`Loss`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/loss/Loss.html) function: A loss function is used to measure how well our model matches the dataset. Because the lower value of the function is better, it's called the \"loss\" function. The Loss is the only required argument to the model\n",
-    "* [`Evaluator`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/evaluator/Evaluator.html) function: An evaluator function is also used to measure how well our model matches the dataset. Unlike the loss, they are only there for people to look at and are not used for optimizing the model. Since many losses are not as intuitive, adding other evaluators such as Accuracy can help to understand how your model is doing. If you know of any useful evaluators, we recommend adding them.\n",
-    "* [`Training Listeners`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/repository/zoo/ZooModel.html): The training listener adds additional functionality to the training process through a listener interface. This can include showing training progress, stopping early if training becomes undefined, or recording performance metrics. We offer several easy sets of [default listeners](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/repository/zoo/ZooModel.html).\n",
+    "* **REQUIRED** [`Loss`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/loss/Loss.html) function: A loss function is used to measure how well our model matches the dataset. Because the lower value of the function is better, it's called the \"loss\" function. The Loss is the only required argument to the model\n",
+    "* [`Evaluator`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/evaluator/Evaluator.html) function: An evaluator function is also used to measure how well our model matches the dataset. Unlike the loss, they are only there for people to look at and are not used for optimizing the model. Since many losses are not as intuitive, adding other evaluators such as Accuracy can help to understand how your model is doing. If you know of any useful evaluators, we recommend adding them.\n",
+    "* [`Training Listeners`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/repository/zoo/ZooModel.html): The training listener adds additional functionality to the training process through a listener interface. This can include showing training progress, stopping early if training becomes undefined, or recording performance metrics. We offer several easy sets of [default listeners](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/repository/zoo/ZooModel.html).\n",
     "\n",
-    "You can also configure other options such as the Device, Initializer, and Optimizer. See [more details](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/training/TrainingConfig.html)."
+    "You can also configure other options such as the Device, Initializer, and Optimizer. See [more details](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/training/TrainingConfig.html)."
    ]
   },
   {
diff --git a/jupyter/tutorial/03_image_classification_with_your_model.ipynb b/jupyter/tutorial/03_image_classification_with_your_model.ipynb
index 75036058a..36c11888b 100644
--- a/jupyter/tutorial/03_image_classification_with_your_model.ipynb
+++ b/jupyter/tutorial/03_image_classification_with_your_model.ipynb
@@ -26,10 +26,10 @@
     "// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/\n",
     "\n",
     "// Add the maven dependencies\n",
-    "%maven ai.djl:api:0.15.0\n",
-    "%maven ai.djl:model-zoo:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-engine:0.15.0\n",
-    "%maven ai.djl.mxnet:mxnet-model-zoo:0.15.0\n",
+    "%maven ai.djl:api:0.16.0\n",
+    "%maven ai.djl:model-zoo:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-engine:0.16.0\n",
+    "%maven ai.djl.mxnet:mxnet-model-zoo:0.16.0\n",
     "%maven org.slf4j:slf4j-simple:1.7.32"
    ]
   },
@@ -100,7 +100,7 @@
     "\n",
     "## Step 3: Create a `Translator`\n",
     "\n",
-    "The [`Translator`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/translate/Translator.html) is used to encapsulate the pre-processing and post-processing functionality of your application. The input to the processInput and processOutput should be single data items, not batches."
+    "The [`Translator`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/translate/Translator.html) is used to encapsulate the pre-processing and post-processing functionality of your application. The input to the processInput and processOutput should be single data items, not batches."
    ]
   },
   {
@@ -141,7 +141,7 @@
    "source": [
     "## Step 4: Create Predictor\n",
     "\n",
-    "Using the translator, we will create a new [`Predictor`](https://javadoc.io/static/ai.djl/api/0.15.0/index.html?ai/djl/inference/Predictor.html). The predictor is the main class to orchestrate the inference process. During inference, a trained model is used to predict values, often for production use cases. The predictor is NOT thread-safe, so if you want to do prediction in parallel, you should call newPredictor multiple times to create a predictor object for each thread."
+    "Using the translator, we will create a new [`Predictor`](https://javadoc.io/static/ai.djl/api/0.16.0/index.html?ai/djl/inference/Predictor.html). The predictor is the main class to orchestrate the inference process. During inference, a trained model is used to predict values, often for production use cases. The predictor is NOT thread-safe, so if you want to do prediction in parallel, you should call newPredictor multiple times to create a predictor object for each thread."
    ]
   },
   {
@@ -159,7 +159,7 @@
    "source": [
     "## Step 5: Run inference\n",
     "\n",
-    "With our predictor, we can simply call the [predict](https://javadoc.io/static/ai.djl/api/0.15.0/ai/djl/inference/Predictor.html#predict-I-) method to run inference. For better performance, you can also call [batchPredict](https://javadoc.io/static/ai.djl/api/0.15.0/ai/djl/inference/Predictor.html#batchPredict-java.util.List-) with a list of input items. Afterwards, the same predictor should be used for further inference calls. "
+    "With our predictor, we can simply call the [predict](https://javadoc.io/static/ai.djl/api/0.16.0/ai/djl/inference/Predictor.html#predict-I-) method to run inference. For better performance, you can also call [batchPredict](https://javadoc.io/static/ai.djl/api/0.16.0/ai/djl/inference/Predictor.html#batchPredict-java.util.List-) with a list of input items. Afterwards, the same predictor should be used for further inference calls. "
    ]
   },
   {
diff --git a/model-zoo/README.md b/model-zoo/README.md
index 1dd8127fa..bee9f15f7 100644
--- a/model-zoo/README.md
+++ b/model-zoo/README.md
@@ -33,7 +33,7 @@ You can pull the model zoo from the central Maven repository by including the fo
 <dependency>
     <groupId>ai.djl</groupId>
     <artifactId>model-zoo</artifactId>
-    <version>0.15.0</version>
+    <version>0.16.0</version>
 </dependency>
 ```
 
diff --git a/tools/conf/pmd.xml b/tools/conf/pmd.xml
index e34cdbe0b..16642b659 100644
--- a/tools/conf/pmd.xml
+++ b/tools/conf/pmd.xml
@@ -235,7 +235,7 @@
         <exclude name="LoggerIsNotStaticFinal"/>
         <exclude name="MethodWithSameNameAsEnclosingClass"/>
         <exclude name="MisplacedNullCheck"/>
-        <exclude name="MissingBreakInSwitch"/>
+        <exclude name="ImplicitSwitchFallThrough"/>
         <exclude name="MissingSerialVersionUID"/>
         <exclude name="MissingStaticMethodInNonInstantiatableClass"/>
         <exclude name="MoreThanOneLogger"/>
@@ -416,7 +416,7 @@
         <exclude name="EmptyIfStmt"/>
         <exclude name="JumbledIncrementer"/>
         <exclude name="LoggerIsNotStaticFinal"/>
-        <exclude name="MissingBreakInSwitch"/>
+        <exclude name="ImplicitSwitchFallThrough"/>
         <exclude name="MoreThanOneLogger"/>
         <exclude name="NonCaseLabelInSwitchStatement"/>
         <exclude name="NonStaticInitializer"/>
diff --git a/tools/gradle/release.gradle b/tools/gradle/release.gradle
index befd70471..5645ad5fe 100644
--- a/tools/gradle/release.gradle
+++ b/tools/gradle/release.gradle
@@ -59,10 +59,14 @@ task increaseFinalVersion {
         collection += fileTree(".").filter {
             it.name.endsWith(".md") || it.name.endsWith("overview.html")
         }
+        collection += file("extensions/benchmark/snapcraft/snapcraft.yaml")
 
         collection.each { File file ->
             file.text = file.text.replaceAll("/${previousVersion}/", "/${djl_version}/")
                     .replaceAll(">${previousVersion}<", ">${djl_version}<")
+                    .replaceAll("'${previousVersion}'", "'${djl_version}'")
+                    .replaceAll("-${previousVersion}", "-${djl_version}")
+                    .replaceAll("_${previousVersion}", "_${djl_version}")
                     .replaceAll(":${previousVersion}([\"\\\\\\n])", ":${djl_version}\$1")
         }
     }


Test patch:
diff --git a/testing/src/main/java/ai/djl/testing/CoverageUtils.java b/testing/src/main/java/ai/djl/testing/CoverageUtils.java
index 1ae9c6256..6b0eb5869 100644
--- a/testing/src/main/java/ai/djl/testing/CoverageUtils.java
+++ b/testing/src/main/java/ai/djl/testing/CoverageUtils.java
@@ -38,6 +38,7 @@ import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.stream.Collectors;
 
+@SuppressWarnings("PMD.AvoidAccessibilityAlteration")
 public final class CoverageUtils {
 
     private CoverageUtils() {}