Repository: deepjavalibrary/djl
Pull request #2118 (2022-11-02 15:48:45)

[api] Handle conflict JNA package issue
## Description ##

Brief description of what this PR is about

- If this change is a backward incompatible change, why must this change be made?
- Interesting edge cases to note here



Patch:
diff --git a/api/src/main/java/ai/djl/training/loss/SoftmaxCrossEntropyLoss.java b/api/src/main/java/ai/djl/training/loss/SoftmaxCrossEntropyLoss.java
index 0269cb7ea..b040de08f 100644
--- a/api/src/main/java/ai/djl/training/loss/SoftmaxCrossEntropyLoss.java
+++ b/api/src/main/java/ai/djl/training/loss/SoftmaxCrossEntropyLoss.java
@@ -22,8 +22,9 @@ import ai.djl.ndarray.index.NDIndex;
  *
  * <p>If {@code sparse_label} is {@code true} (default), {@code label} should contain integer
  * category indicators. Then, \(L = -\sum_i \log p_{i, label_i}\). If {@code sparse_label} is {@code
- * false}, {@code label} should contain probability distribution and its shape should be the same as
- * the shape of {@code prediction}. Then, \(L = -\sum_i \sum_j {label}_j \log p_{ij}\).
+ * false}, {@code label} should be one-hot class coding or probability distribution and its shape
+ * should be the same as the shape of {@code prediction}. Then, \(L = -\sum_i \sum_j {label}_j \log
+ * p_{ij}\).
  */
 public class SoftmaxCrossEntropyLoss extends Loss {
 
@@ -54,8 +55,8 @@ public class SoftmaxCrossEntropyLoss extends Loss {
      * @param name the name of the loss
      * @param weight the weight to apply on the loss value, default 1
      * @param classAxis the axis that represents the class probabilities, default -1
-     * @param sparseLabel whether labels are rank-1 integer array of [batch_size] (false) or rank-2
-     *     one-hot of [batch_size, n-class] (true), default true
+     * @param sparseLabel whether labels are rank-1 integer array of [batch_size] (true) or rank-2
+     *     one-hot or probability distribution of shape [batch_size, n-class] (false), default true
      * @param fromLogit if true, the inputs are assumed to be the numbers before being applied with
      *     softmax. Then logSoftmax will be applied to input, default true
      */
diff --git a/api/src/main/java/ai/djl/util/cuda/CudaUtils.java b/api/src/main/java/ai/djl/util/cuda/CudaUtils.java
index 01faa05a9..3c28283a2 100644
--- a/api/src/main/java/ai/djl/util/cuda/CudaUtils.java
+++ b/api/src/main/java/ai/djl/util/cuda/CudaUtils.java
@@ -187,6 +187,10 @@ public final class CudaUtils {
             logger.debug("cudart library not found.");
             logger.trace("", e);
             return null;
+        } catch (IncompatibleClassChangeError e) {
+            logger.warn("You have a conflict version of JNA in the classpath.");
+            logger.debug("", e);
+            return null;
         } catch (SecurityException e) {
             logger.warn("Access denied during loading cudart library.");
             logger.trace("", e);
diff --git a/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtEngine.java b/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtEngine.java
index bb49ac51c..6bf773e15 100644
--- a/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtEngine.java
+++ b/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtEngine.java
@@ -99,7 +99,7 @@ public final class OrtEngine extends Engine {
     /** {@inheritDoc} */
     @Override
     public String getVersion() {
-        return "1.12.1";
+        return "1.13.1";
     }
 
     /** {@inheritDoc} */
diff --git a/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtSymbolBlock.java b/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtSymbolBlock.java
index e05f95568..aa54b43f3 100644
--- a/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtSymbolBlock.java
+++ b/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtSymbolBlock.java
@@ -25,12 +25,12 @@ import ai.djl.nn.SymbolBlock;
 import ai.djl.training.ParameterStore;
 import ai.djl.util.PairList;
 import ai.onnxruntime.OnnxJavaType;
+import ai.onnxruntime.OnnxMap;
 import ai.onnxruntime.OnnxSequence;
 import ai.onnxruntime.OnnxTensor;
 import ai.onnxruntime.OnnxValue;
 import ai.onnxruntime.OrtException;
 import ai.onnxruntime.OrtSession;
-import ai.onnxruntime.SequenceInfo;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -135,7 +135,12 @@ public class OrtSymbolBlock extends AbstractSymbolBlock implements AutoCloseable
                 output.add(manager.createInternal((OnnxTensor) value));
             } else if (value instanceof OnnxSequence) {
                 // TODO: avoid memory copying to heap
-                output.add(seq2Nd((OnnxSequence) value));
+                OnnxSequence seq = (OnnxSequence) value;
+                if (seq.getInfo().isSequenceOfMaps()) {
+                    output.add(seq2Nd(seq));
+                } else {
+                    output.addAll(seq2NdList(seq));
+                }
             } else {
                 throw new UnsupportedOperationException("Unsupported output type! " + r.getKey());
             }
@@ -146,40 +151,36 @@ public class OrtSymbolBlock extends AbstractSymbolBlock implements AutoCloseable
     @SuppressWarnings("unchecked")
     private NDArray seq2Nd(OnnxSequence seq) {
         try {
-            List<Object> values = seq.getValue();
-            OnnxJavaType type = seq.getInfo().sequenceType;
-            Shape shape = new Shape(values.size());
+            List<OnnxMap> values = (List<OnnxMap>) seq.getValue();
             DataType dp;
-            SequenceInfo info = seq.getInfo();
-            if (info.sequenceOfMaps) {
-                type = info.mapInfo.valueType;
-                List<Object> valuesTmp = new ArrayList<>();
-                values.forEach(map -> valuesTmp.addAll(((Map<Object, Object>) map).values()));
-                shape = new Shape(values.size(), valuesTmp.size() / values.size());
-                values = valuesTmp;
+            List<Object> finalData = new ArrayList<>();
+            OnnxJavaType type = seq.getInfo().mapInfo.valueType;
+            for (OnnxMap map : values) {
+                finalData.addAll(((Map<Object, Object>) map.getValue()).values());
             }
-            ByteBuffer buffer = ByteBuffer.allocate(values.size() * type.size);
+            Shape shape = new Shape(values.size(), finalData.size() / values.size());
+            ByteBuffer buffer = ByteBuffer.allocate(finalData.size() * type.size);
             switch (type) {
                 case FLOAT:
-                    values.forEach(ele -> buffer.putFloat((Float) ele));
+                    finalData.forEach(ele -> buffer.putFloat((Float) ele));
                     buffer.rewind();
                     return manager.create(buffer.asFloatBuffer(), shape, DataType.FLOAT32);
                 case DOUBLE:
-                    values.forEach(ele -> buffer.putDouble((Double) ele));
+                    finalData.forEach(ele -> buffer.putDouble((Double) ele));
                     buffer.rewind();
                     return manager.create(buffer.asDoubleBuffer(), shape, DataType.FLOAT64);
                 case BOOL:
                 case INT8:
                     dp = (type == OnnxJavaType.BOOL) ? DataType.BOOLEAN : DataType.INT8;
-                    values.forEach(ele -> buffer.put((Byte) ele));
+                    finalData.forEach(ele -> buffer.put((Byte) ele));
                     buffer.rewind();
                     return manager.create(buffer, shape, dp);
                 case INT32:
-                    values.forEach(ele -> buffer.putInt((Integer) ele));
+                    finalData.forEach(ele -> buffer.putInt((Integer) ele));
                     buffer.rewind();
                     return manager.create(buffer.asIntBuffer(), shape, DataType.INT32);
                 case INT64:
-                    values.forEach(ele -> buffer.putLong((Long) ele));
+                    finalData.forEach(ele -> buffer.putLong((Long) ele));
                     buffer.rewind();
                     return manager.create(buffer.asLongBuffer(), shape, DataType.INT64);
                 default:
@@ -190,6 +191,18 @@ public class OrtSymbolBlock extends AbstractSymbolBlock implements AutoCloseable
         }
     }
 
+    private NDList seq2NdList(OnnxSequence sequence) {
+        try {
+            NDList list = new NDList();
+            for (OnnxValue value : sequence.getValue()) {
+                list.add(manager.createInternal((OnnxTensor) value));
+            }
+            return list;
+        } catch (OrtException e) {
+            throw new EngineException(e);
+        }
+    }
+
     /** {@inheritDoc} */
     @Override
     public void close() {
diff --git a/gradle.properties b/gradle.properties
index 275aaed1d..7f754b706 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -18,12 +18,12 @@ tensorflow_version=2.7.0
 tflite_version=2.6.2
 dlr_version=1.6.0
 trt_version=8.4.1
-onnxruntime_version=1.12.1
+onnxruntime_version=1.13.1
 paddlepaddle_version=2.2.2
 sentencepiece_version=0.1.96
 tokenizers_version=0.12.0
 fasttext_version=0.9.2
-xgboost_version=1.6.1
+xgboost_version=1.6.2
 lightgbm_version=3.2.110
 rapis_version=22.04.0
 


Test patch:
diff --git a/engines/ml/xgboost/src/test/java/ai/djl/ml/xgboost/XgbModelTest.java b/engines/ml/xgboost/src/test/java/ai/djl/ml/xgboost/XgbModelTest.java
index 8dffbdbbc..e354f43ad 100644
--- a/engines/ml/xgboost/src/test/java/ai/djl/ml/xgboost/XgbModelTest.java
+++ b/engines/ml/xgboost/src/test/java/ai/djl/ml/xgboost/XgbModelTest.java
@@ -54,7 +54,7 @@ public class XgbModelTest {
     @Test
     public void testVersion() {
         Engine engine = Engine.getEngine("XGBoost");
-        Assert.assertEquals("1.6.1", engine.getVersion());
+        Assert.assertEquals("1.6.2", engine.getVersion());
     }
 
     /*