Repository: deepjavalibrary/djl
Pull request #1984 (2022-09-02 15:23:05)

[huggingface] Adds Huggingface ModelZoo
Change-Id: Ief99e4b5449c95a75582ded9a9e2549e582387c5

## 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/Application.java b/api/src/main/java/ai/djl/Application.java
index 81e98b13f..cfd8b41b3 100644
--- a/api/src/main/java/ai/djl/Application.java
+++ b/api/src/main/java/ai/djl/Application.java
@@ -70,20 +70,24 @@ public class Application {
                 return CV.IMAGE_ENHANCEMENT;
             case "nlp":
                 return NLP.ANY;
-            case "nlp/question_answer":
-                return NLP.QUESTION_ANSWER;
-            case "nlp/text_classification":
-                return NLP.TEXT_CLASSIFICATION;
-            case "nlp/sentiment_analysis":
-                return NLP.SENTIMENT_ANALYSIS;
-            case "nlp/word_embedding":
-                return NLP.WORD_EMBEDDING;
+            case "nlp/fill_mask":
+                return NLP.FILL_MASK;
             case "nlp/machine_translation":
                 return NLP.MACHINE_TRANSLATION;
             case "nlp/multiple_choice":
                 return NLP.MULTIPLE_CHOICE;
+            case "nlp/question_answer":
+                return NLP.QUESTION_ANSWER;
+            case "nlp/sentiment_analysis":
+                return NLP.SENTIMENT_ANALYSIS;
+            case "nlp/text_classification":
+                return NLP.TEXT_CLASSIFICATION;
             case "nlp/text_embedding":
                 return NLP.TEXT_EMBEDDING;
+            case "nlp/token_classification":
+                return NLP.TOKEN_CLASSIFICATION;
+            case "nlp/word_embedding":
+                return NLP.WORD_EMBEDDING;
             case "tabular":
                 return Tabular.ANY;
             case "tabular/linear_regression":
@@ -210,6 +214,12 @@ public class Application {
         /** Any NLP application, including those in {@link NLP}. */
         Application ANY = new Application("nlp");
 
+        /**
+         * An application that masking some words in a sentence and predicting which words should
+         * replace those masks.
+         */
+        Application FILL_MASK = new Application("nlp/fill_mask");
+
         /**
          * An application that a reference document and a question about the document and returns
          * text answering the question.
@@ -228,11 +238,17 @@ public class Application {
         Application TEXT_CLASSIFICATION = new Application("nlp/text_classification");
 
         /**
-         * An application that classifies text into positive or negative, an specific case of {@link
+         * An application that classifies text into positive or negative, a specific case of {@link
          * #TEXT_CLASSIFICATION}.
          */
         Application SENTIMENT_ANALYSIS = new Application("nlp/sentiment_analysis");
 
+        /**
+         * A natural language understanding application that assigns a label to some tokens in a
+         * text.
+         */
+        Application TOKEN_CLASSIFICATION = new Application("nlp/token_classification");
+
         /**
          * An application that takes a word and returns a feature vector that represents the word.
          *
diff --git a/api/src/main/java/ai/djl/ndarray/BaseNDManager.java b/api/src/main/java/ai/djl/ndarray/BaseNDManager.java
index dd7bcaa46..698e049db 100644
--- a/api/src/main/java/ai/djl/ndarray/BaseNDManager.java
+++ b/api/src/main/java/ai/djl/ndarray/BaseNDManager.java
@@ -403,10 +403,21 @@ public abstract class BaseNDManager implements NDManager {
      * @param expected the expected size
      * @throws IllegalArgumentException if buffer size is invalid
      */
-    public static void validateBufferSize(Buffer buffer, DataType dataType, int expected) {
+    public static void validateBuffer(Buffer buffer, DataType dataType, int expected) {
+        boolean isByteBuffer = buffer instanceof ByteBuffer;
+        DataType type = DataType.fromBuffer(buffer);
+        if (type != dataType && !isByteBuffer) {
+            // It's ok if type != datatype and buffer is ByteBuffer,
+            // since buffer will be copied into ByteBuffer
+            throw new IllegalArgumentException(
+                    "The input data type: "
+                            + type
+                            + " does not match target array data type: "
+                            + dataType);
+        }
+
         int remaining = buffer.remaining();
-        int expectedSize =
-                buffer instanceof ByteBuffer ? dataType.getNumOfBytes() * expected : expected;
+        int expectedSize = isByteBuffer ? dataType.getNumOfBytes() * expected : expected;
         if (remaining < expectedSize) {
             throw new IllegalArgumentException(
                     "The NDArray size is: " + expected + ", but buffer size is: " + remaining);
diff --git a/api/src/main/java/ai/djl/ndarray/NDArray.java b/api/src/main/java/ai/djl/ndarray/NDArray.java
index 8658f7389..d3df0631d 100644
--- a/api/src/main/java/ai/djl/ndarray/NDArray.java
+++ b/api/src/main/java/ai/djl/ndarray/NDArray.java
@@ -400,9 +400,9 @@ public interface NDArray extends NDResource, BytesSupplier {
     /**
      * Sets this {@code NDArray} value from {@link Buffer}.
      *
-     * @param data the input buffered data
+     * @param buffer the input buffered data
      */
-    void set(Buffer data);
+    void set(Buffer buffer);
 
     /**
      * Sets this {@code NDArray} value from an array of floats.
diff --git a/api/src/main/java/ai/djl/ndarray/NDArrayAdapter.java b/api/src/main/java/ai/djl/ndarray/NDArrayAdapter.java
index 940ad0de8..2ff23df27 100644
--- a/api/src/main/java/ai/djl/ndarray/NDArrayAdapter.java
+++ b/api/src/main/java/ai/djl/ndarray/NDArrayAdapter.java
@@ -211,8 +211,8 @@ public abstract class NDArrayAdapter implements NDArray {
 
     /** {@inheritDoc} */
     @Override
-    public void set(Buffer data) {
-        NDArray array = manager.create(data, getShape(), getDataType());
+    public void set(Buffer buffer) {
+        NDArray array = manager.create(buffer, getShape(), getDataType());
         intern(array);
         array.detach();
     }
diff --git a/api/src/main/java/ai/djl/repository/RepositoryFactoryImpl.java b/api/src/main/java/ai/djl/repository/RepositoryFactoryImpl.java
index 8abb4ca44..622cc3d74 100644
--- a/api/src/main/java/ai/djl/repository/RepositoryFactoryImpl.java
+++ b/api/src/main/java/ai/djl/repository/RepositoryFactoryImpl.java
@@ -83,7 +83,7 @@ class RepositoryFactoryImpl implements RepositoryFactory {
             return new SimpleUrlRepository(name, uri, modelName);
         }
 
-        Path path = parseFilePath(uri);
+        Path path = Paths.get(parseFilePath(uri));
         String fileName = path.toFile().getName();
         if (FilenameUtils.isArchiveFile(fileName)) {
             fileName = FilenameUtils.getNamePart(fileName);
@@ -119,7 +119,7 @@ class RepositoryFactoryImpl implements RepositoryFactory {
         return registry;
     }
 
-    static Path parseFilePath(URI uri) {
+    static String parseFilePath(URI uri) {
         String uriPath = uri.getPath();
         if (uriPath == null) {
             uriPath = uri.getSchemeSpecificPart();
@@ -131,7 +131,7 @@ class RepositoryFactoryImpl implements RepositoryFactory {
         if (uriPath.startsWith("/") && System.getProperty("os.name").startsWith("Win")) {
             uriPath = uriPath.substring(1);
         }
-        return Paths.get(uriPath);
+        return uriPath;
     }
 
     private static final class JarRepositoryFactory implements RepositoryFactory {
@@ -154,7 +154,7 @@ class RepositoryFactoryImpl implements RepositoryFactory {
                 throw new IllegalArgumentException("Resource not found: " + uri, e);
             }
 
-            Path path = parseFilePath(uri);
+            Path path = Paths.get(parseFilePath(uri));
             String fileName = path.toFile().getName();
             if (!FilenameUtils.isArchiveFile(fileName)) {
                 throw new IllegalArgumentException("Only archive file is supported for res URL.");
@@ -176,7 +176,7 @@ class RepositoryFactoryImpl implements RepositoryFactory {
         /** {@inheritDoc} */
         @Override
         public Repository newInstance(String name, URI uri) {
-            Path path = parseFilePath(uri);
+            Path path = Paths.get(parseFilePath(uri));
             if (Files.exists(path) && Files.isDirectory(path)) {
                 try {
                     if (Files.walk(path)
@@ -220,7 +220,7 @@ class RepositoryFactoryImpl implements RepositoryFactory {
             if (groupId == null) {
                 throw new IllegalArgumentException("Invalid djl URL: " + uri);
             }
-            String artifactId = parseFilePath(uri).toString();
+            String artifactId = parseFilePath(uri);
             if (artifactId.startsWith("/")) {
                 artifactId = artifactId.substring(1);
             }
diff --git a/api/src/main/java/ai/djl/util/Utils.java b/api/src/main/java/ai/djl/util/Utils.java
index b4332194a..634964ad5 100644
--- a/api/src/main/java/ai/djl/util/Utils.java
+++ b/api/src/main/java/ai/djl/util/Utils.java
@@ -22,6 +22,7 @@ import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.FileVisitOption;
 import java.nio.file.Files;
@@ -430,4 +431,31 @@ public final class Utils {
         }
         return Collections.emptyMap();
     }
+
+    /**
+     * Opens a connection to this URL and returns an InputStream for reading from that connection.
+     *
+     * @param url the url to open
+     * @return an input stream for reading from the URL connection.
+     * @throws IOException if an I/O exception occurs
+     */
+    public static InputStream openUrl(String url) throws IOException {
+        return openUrl(new URL(url));
+    }
+
+    /**
+     * Opens a connection to this URL and returns an InputStream for reading from that connection.
+     *
+     * @param url the url to open
+     * @return an input stream for reading from the URL connection.
+     * @throws IOException if an I/O exception occurs
+     */
+    public static InputStream openUrl(URL url) throws IOException {
+        String protocol = url.getProtocol();
+        if (Boolean.getBoolean("offline")
+                && ("http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol))) {
+            throw new IOException("Offline model is enabled.");
+        }
+        return new BufferedInputStream(url.openStream());
+    }
 }
diff --git a/engines/dlr/dlr-engine/src/main/java/ai/djl/dlr/engine/DlrNDManager.java b/engines/dlr/dlr-engine/src/main/java/ai/djl/dlr/engine/DlrNDManager.java
index c77aadb10..aa834b84f 100644
--- a/engines/dlr/dlr-engine/src/main/java/ai/djl/dlr/engine/DlrNDManager.java
+++ b/engines/dlr/dlr-engine/src/main/java/ai/djl/dlr/engine/DlrNDManager.java
@@ -81,7 +81,7 @@ public class DlrNDManager extends BaseNDManager {
             throw new UnsupportedOperationException("DlrNDArray only supports float32.");
         }
         int size = Math.toIntExact(shape.size());
-        BaseNDManager.validateBufferSize(data, dataType, size);
+        BaseNDManager.validateBuffer(data, dataType, size);
         if (data instanceof ByteBuffer) {
             return new DlrNDArray(this, alternativeManager, (ByteBuffer) data, shape, dataType);
         }
diff --git a/engines/dlr/dlr-engine/src/main/java/ai/djl/dlr/jni/LibUtils.java b/engines/dlr/dlr-engine/src/main/java/ai/djl/dlr/jni/LibUtils.java
index 3353e9657..f19da8261 100644
--- a/engines/dlr/dlr-engine/src/main/java/ai/djl/dlr/jni/LibUtils.java
+++ b/engines/dlr/dlr-engine/src/main/java/ai/djl/dlr/jni/LibUtils.java
@@ -200,7 +200,7 @@ public final class LibUtils {
         }
         String link = "https://publish.djl.ai/dlr-" + matcher.group(1) + "/native";
         Path tmp = null;
-        try (InputStream is = new URL(link + "/files.txt").openStream()) {
+        try (InputStream is = Utils.openUrl(link + "/files.txt")) {
             Files.createDirectories(dlrCacheRoot);
             List<String> lines = Utils.readLines(is);
             if (flavor.startsWith("cu")
@@ -224,7 +224,7 @@ public final class LibUtils {
                     URL url = new URL(link + '/' + line);
                     String fileName = line.substring(line.lastIndexOf('/') + 1);
                     logger.info("Downloading {} ...", url);
-                    try (InputStream fis = url.openStream()) {
+                    try (InputStream fis = Utils.openUrl(url)) {
                         Files.copy(fis, tmp.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
                     }
                 }
diff --git a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/MxNDArray.java b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/MxNDArray.java
index 78b041ba4..57a2a5bb8 100644
--- a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/MxNDArray.java
+++ b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/engine/MxNDArray.java
@@ -302,18 +302,18 @@ public class MxNDArray extends NativeResource<Pointer> implements LazyNDArray {
 
     /** {@inheritDoc} */
     @Override
-    public void set(Buffer data) {
+    public void set(Buffer buffer) {
         int size = Math.toIntExact(size());
         DataType type = getDataType();
-        BaseNDManager.validateBufferSize(data, type, size);
-        if (data.isDirect()) {
-            JnaUtils.syncCopyFromCPU(getHandle(), data, size);
+        BaseNDManager.validateBuffer(buffer, type, size);
+        if (buffer.isDirect()) {
+            JnaUtils.syncCopyFromCPU(getHandle(), buffer, size);
             return;
         }
 
-        ByteBuffer buf = manager.allocateDirect(size * type.getNumOfBytes());
-        BaseNDManager.copyBuffer(data, buf);
-        JnaUtils.syncCopyFromCPU(getHandle(), buf, size);
+        ByteBuffer bb = manager.allocateDirect(size * type.getNumOfBytes());
+        BaseNDManager.copyBuffer(buffer, bb);
+        JnaUtils.syncCopyFromCPU(getHandle(), bb, size);
     }
 
     /** {@inheritDoc} */
diff --git a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/jna/LibUtils.java b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/jna/LibUtils.java
index 6d62bb495..8dc9ca6b3 100644
--- a/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/jna/LibUtils.java
+++ b/engines/mxnet/mxnet-engine/src/main/java/ai/djl/mxnet/jna/LibUtils.java
@@ -212,7 +212,7 @@ public final class LibUtils {
 
         Path tmp = null;
         String link = "https://publish.djl.ai/mxnet-" + matcher.group(1);
-        try (InputStream is = new URL(link + "/files.txt").openStream()) {
+        try (InputStream is = Utils.openUrl(link + "/files.txt")) {
             Files.createDirectories(cacheFolder);
             tmp = Files.createTempDirectory(cacheFolder, "tmp");
 
@@ -272,7 +272,7 @@ public final class LibUtils {
                         }
                     }
                     logger.info("Downloading {} ...", fileName);
-                    try (InputStream fis = new GZIPInputStream(url.openStream())) {
+                    try (InputStream fis = new GZIPInputStream(Utils.openUrl(url))) {
                         Files.copy(fis, tmp.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
                     }
                 }
diff --git a/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtNDManager.java b/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtNDManager.java
index e884d125a..0136e3e77 100644
--- a/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtNDManager.java
+++ b/engines/onnxruntime/onnxruntime-engine/src/main/java/ai/djl/onnxruntime/engine/OrtNDManager.java
@@ -73,7 +73,7 @@ public class OrtNDManager extends BaseNDManager {
                     "Use NDManager.create(String[], Shape) to create String NDArray.");
         }
         int size = Math.toIntExact(shape.size());
-        BaseNDManager.validateBufferSize(data, dataType, size);
+        BaseNDManager.validateBuffer(data, dataType, size);
         OnnxTensor tensor = OrtUtils.toTensor(env, data, shape, dataType);
         return new OrtNDArray(this, alternativeManager, tensor);
     }
diff --git a/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpNDManager.java b/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpNDManager.java
index a4c38ebdb..8bfe0e850 100644
--- a/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpNDManager.java
+++ b/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/engine/PpNDManager.java
@@ -91,7 +91,7 @@ public class PpNDManager extends BaseNDManager {
     @Override
     public PpNDArray create(Buffer data, Shape shape, DataType dataType) {
         int size = Math.toIntExact(shape.size());
-        BaseNDManager.validateBufferSize(data, dataType, size);
+        BaseNDManager.validateBuffer(data, dataType, size);
         if (data.isDirect() && data instanceof ByteBuffer) {
             return JniUtils.createNdArray(this, (ByteBuffer) data, shape, dataType);
         }
diff --git a/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/jni/LibUtils.java b/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/jni/LibUtils.java
index 3c67fd9d0..16249b3c9 100644
--- a/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/jni/LibUtils.java
+++ b/engines/paddlepaddle/paddlepaddle-engine/src/main/java/ai/djl/paddlepaddle/jni/LibUtils.java
@@ -265,7 +265,7 @@ public final class LibUtils {
 
         Path tmp = null;
         String link = "https://publish.djl.ai/paddlepaddle-" + matcher.group(1);
-        try (InputStream is = new URL(link + "/files.txt").openStream()) {
+        try (InputStream is = Utils.openUrl(link + "/files.txt")) {
             Files.createDirectories(cacheDir);
 
             List<String> lines = Utils.readLines(is);
@@ -291,7 +291,7 @@ public final class LibUtils {
                     URL url = new URL(link + '/' + line);
                     String fileName = line.substring(line.lastIndexOf('/') + 1, line.length() - 3);
                     logger.info("Downloading {} ...", url);
-                    try (InputStream fis = new GZIPInputStream(url.openStream())) {
+                    try (InputStream fis = new GZIPInputStream(Utils.openUrl(url))) {
                         Files.copy(fis, tmp.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
                     }
                 }
diff --git a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtNDArray.java b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtNDArray.java
index 2829fee3f..aa2059b7e 100644
--- a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtNDArray.java
+++ b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtNDArray.java
@@ -225,24 +225,24 @@ public class PtNDArray extends NativeResource<Long> implements NDArray {
 
     /** {@inheritDoc} */
     @Override
-    public void set(Buffer data) {
+    public void set(Buffer buffer) {
         int size = Math.toIntExact(size());
-        BaseNDManager.validateBufferSize(data, getDataType(), size);
+        DataType type = getDataType();
+        BaseNDManager.validateBuffer(buffer, type, size);
         // TODO how do we handle the exception happened in the middle
         dataRef = null;
-        if (data.isDirect() && data instanceof ByteBuffer) {
+        if (buffer.isDirect() && buffer instanceof ByteBuffer) {
             // If NDArray is on the GPU, it is native code responsibility to control the data life
             // cycle
             if (!getDevice().isGpu()) {
-                dataRef = (ByteBuffer) data;
+                dataRef = (ByteBuffer) buffer;
             }
-            JniUtils.set(this, (ByteBuffer) data);
+            JniUtils.set(this, (ByteBuffer) buffer);
             return;
         }
         // int8, uint8, boolean use ByteBuffer, so need to explicitly input DataType
-        DataType inputType = DataType.fromBuffer(data);
-        ByteBuffer buf = manager.allocateDirect(size * inputType.getNumOfBytes());
-        BaseNDManager.copyBuffer(data, buf);
+        ByteBuffer buf = manager.allocateDirect(size * type.getNumOfBytes());
+        BaseNDManager.copyBuffer(buffer, buf);
 
         // If NDArray is on the GPU, it is native code responsibility to control the data life cycle
         if (!getDevice().isGpu()) {
diff --git a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtNDManager.java b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtNDManager.java
index 307edb414..979a0493e 100644
--- a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtNDManager.java
+++ b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/engine/PtNDManager.java
@@ -66,7 +66,7 @@ public class PtNDManager extends BaseNDManager {
     @Override
     public PtNDArray create(Buffer data, Shape shape, DataType dataType) {
         int size = Math.toIntExact(shape.size());
-        BaseNDManager.validateBufferSize(data, dataType, size);
+        BaseNDManager.validateBuffer(data, dataType, size);
         if (data.isDirect() && data instanceof ByteBuffer) {
             return JniUtils.createNdFromByteBuffer(
                     this, (ByteBuffer) data, shape, dataType, SparseFormat.DENSE, device);
diff --git a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/LibUtils.java b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/LibUtils.java
index d8c6532a5..e4dfa651e 100644
--- a/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/LibUtils.java
+++ b/engines/pytorch/pytorch-engine/src/main/java/ai/djl/pytorch/jni/LibUtils.java
@@ -229,7 +229,7 @@ public final class LibUtils {
             String jniVersion = null;
             if (url != null) {
                 Properties prop = new Properties();
-                try (InputStream is = url.openStream()) {
+                try (InputStream is = Utils.openUrl(url)) {
                     prop.load(is);
                 }
                 jniVersion = prop.getProperty("jni_version");
@@ -391,7 +391,7 @@ public final class LibUtils {
         Path indexFile = cacheDir.resolve(version + ".txt");
         if (Files.notExists(indexFile)) {
             Path tempFile = cacheDir.resolve(version + ".tmp");
-            try (InputStream is = new URL(link + "/files.txt").openStream()) {
+            try (InputStream is = Utils.openUrl(link + "/files.txt")) {
                 Files.createDirectories(cacheDir);
                 Files.copy(is, tempFile, StandardCopyOption.REPLACE_EXISTING);
                 Utils.moveQuietly(tempFile, indexFile);
@@ -453,7 +453,7 @@ public final class LibUtils {
                     String fileName = line.substring(line.lastIndexOf('/') + 1, line.length() - 3);
                     fileName = URLDecoder.decode(fileName, "UTF-8");
                     logger.info("Downloading {} ...", url);
-                    try (InputStream fis = new GZIPInputStream(url.openStream())) {
+                    try (InputStream fis = new GZIPInputStream(Utils.openUrl(url))) {
                         Files.copy(fis, tmp.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
                     }
                 }
@@ -494,7 +494,7 @@ public final class LibUtils {
                         + JNI_LIB_NAME;
         logger.info("Downloading jni {} to cache ...", url);
         Path tmp = null;
-        try (InputStream is = new URL(url).openStream()) {
+        try (InputStream is = Utils.openUrl(url)) {
             Files.createDirectories(cacheDir);
             tmp = Files.createTempFile(cacheDir, "jni", "tmp");
             Files.copy(is, tmp, StandardCopyOption.REPLACE_EXISTING);
diff --git a/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfNDArray.java b/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfNDArray.java
index 915438789..fb71bb323 100644
--- a/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfNDArray.java
+++ b/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfNDArray.java
@@ -186,20 +186,21 @@ public class TfNDArray extends NativeResource<TFE_TensorHandle> implements NDArr
 
     /** {@inheritDoc} */
     @Override
-    public void set(Buffer data) {
+    public void set(Buffer buffer) {
         if (getDevice().isGpu()) {
             // TODO: Implement set for GPU
             throw new UnsupportedOperationException("GPU Tensor cannot be modified after creation");
         }
         int size = Math.toIntExact(getShape().size());
-        BaseNDManager.validateBufferSize(data, getDataType(), size);
-        if (data instanceof ByteBuffer) {
-            JavacppUtils.setByteBuffer(getHandle(), (ByteBuffer) data);
+        DataType type = getDataType();
+        BaseNDManager.validateBuffer(buffer, type, size);
+        if (buffer instanceof ByteBuffer) {
+            JavacppUtils.setByteBuffer(getHandle(), (ByteBuffer) buffer);
             return;
         }
-        ByteBuffer buf = getManager().allocateDirect(size * getDataType().getNumOfBytes());
-        BaseNDManager.copyBuffer(data, buf);
-        JavacppUtils.setByteBuffer(getHandle(), buf);
+        ByteBuffer bb = getManager().allocateDirect(size * type.getNumOfBytes());
+        BaseNDManager.copyBuffer(buffer, bb);
+        JavacppUtils.setByteBuffer(getHandle(), bb);
     }
 
     /** {@inheritDoc} */
diff --git a/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfNDManager.java b/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfNDManager.java
index 407d67baa..622b3c44c 100644
--- a/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfNDManager.java
+++ b/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/TfNDManager.java
@@ -85,7 +85,7 @@ public class TfNDManager extends BaseNDManager {
                     "Use NDManager.create(String[], Charset, Shape) to create String NDArray.");
         }
         int size = Math.toIntExact(shape.size());
-        BaseNDManager.validateBufferSize(data, dataType, size);
+        BaseNDManager.validateBuffer(data, dataType, size);
         if (data.isDirect() && data instanceof ByteBuffer) {
             TFE_TensorHandle handle =
                     JavacppUtils.createTFETensorFromByteBuffer(
diff --git a/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/javacpp/LibUtils.java b/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/javacpp/LibUtils.java
index efe6e45cc..6d92d414a 100644
--- a/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/javacpp/LibUtils.java
+++ b/engines/tensorflow/tensorflow-engine/src/main/java/ai/djl/tensorflow/engine/javacpp/LibUtils.java
@@ -169,7 +169,7 @@ public final class LibUtils {
 
         Path tmp = null;
         String link = "https://publish.djl.ai/tensorflow-" + matcher.group(1);
-        try (InputStream is = new URL(link + "/files.txt").openStream()) {
+        try (InputStream is = Utils.openUrl(link + "/files.txt")) {
             Files.createDirectories(cacheDir);
             tmp = Files.createTempDirectory(cacheDir, "tmp");
 
@@ -218,7 +218,7 @@ public final class LibUtils {
                 URL url = new URL(link + '/' + line.replace("+", "%2B"));
                 String fileName = line.substring(line.lastIndexOf('/') + 1, line.length() - 3);
                 logger.info("Downloading {} ...", url);
-                try (InputStream fis = new GZIPInputStream(url.openStream())) {
+                try (InputStream fis = new GZIPInputStream(Utils.openUrl(url))) {
                     Files.copy(fis, tmp.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
                 }
             }
diff --git a/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtNDArray.java b/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtNDArray.java
index 7f59bc8a9..3461e35ef 100644
--- a/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtNDArray.java
+++ b/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtNDArray.java
@@ -62,9 +62,9 @@ public class TrtNDArray extends NDArrayAdapter {
 
     /** {@inheritDoc} */
     @Override
-    public void set(Buffer data) {
+    public void set(Buffer buffer) {
         int size = Math.toIntExact(shape.size());
-        BaseNDManager.validateBufferSize(data, dataType, size);
-        BaseNDManager.copyBuffer(data, this.data);
+        BaseNDManager.validateBuffer(buffer, dataType, size);
+        BaseNDManager.copyBuffer(buffer, data);
     }
 }
diff --git a/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtNDManager.java b/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtNDManager.java
index 6fa8c1967..2307e32d7 100644
--- a/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtNDManager.java
+++ b/engines/tensorrt/src/main/java/ai/djl/tensorrt/engine/TrtNDManager.java
@@ -72,7 +72,7 @@ public class TrtNDManager extends BaseNDManager {
     @Override
     public TrtNDArray create(Buffer data, Shape shape, DataType dataType) {
         int size = Math.toIntExact(shape.size());
-        BaseNDManager.validateBufferSize(data, dataType, size);
+        BaseNDManager.validateBuffer(data, dataType, size);
         if (data.isDirect() && data instanceof ByteBuffer) {
             return new TrtNDArray(this, alternativeManager, (ByteBuffer) data, shape, dataType);
         }
diff --git a/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/LibUtils.java b/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/LibUtils.java
index 03d6946c8..67eca831a 100644
--- a/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/LibUtils.java
+++ b/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/LibUtils.java
@@ -123,7 +123,7 @@ public final class LibUtils {
         String link = "https://publish.djl.ai/tflite/" + matcher.group(1);
 
         Path tmp = null;
-        try (InputStream is = new URL(link + "/files.txt").openStream()) {
+        try (InputStream is = Utils.openUrl(link + "/files.txt")) {
             Files.createDirectories(cacheDir);
             List<String> lines = Utils.readLines(is);
             if (flavor.startsWith("cu")
@@ -148,7 +148,7 @@ public final class LibUtils {
                     URL url = new URL(link + '/' + line);
                     String fileName = line.substring(line.lastIndexOf('/') + 1, line.length() - 3);
                     logger.info("Downloading {} ...", url);
-                    try (InputStream fis = new GZIPInputStream(url.openStream())) {
+                    try (InputStream fis = new GZIPInputStream(Utils.openUrl(url))) {
                         Files.copy(fis, tmp.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
                     }
                 }
diff --git a/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/TfLiteNDManager.java b/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/TfLiteNDManager.java
index 70a321c4a..d0b9f8d20 100644
--- a/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/TfLiteNDManager.java
+++ b/engines/tflite/tflite-engine/src/main/java/ai/djl/tflite/engine/TfLiteNDManager.java
@@ -63,7 +63,7 @@ public class TfLiteNDManager extends BaseNDManager {
     @Override
     public TfLiteNDArray create(Buffer data, Shape shape, DataType dataType) {
         int size = Math.toIntExact(shape.size());
-        BaseNDManager.validateBufferSize(data, dataType, size);
+        BaseNDManager.validateBuffer(data, dataType, size);
         if (data.isDirect() && data instanceof ByteBuffer) {
             return new TfLiteNDArray(this, alternativeManager, (ByteBuffer) data, shape, dataType);
         }
diff --git a/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/HfModelZoo.java b/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/HfModelZoo.java
new file mode 100644
index 000000000..15fed4572
--- /dev/null
+++ b/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/HfModelZoo.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
+ * with the License. A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+package ai.djl.huggingface.zoo;
+
+import ai.djl.Application;
+import ai.djl.Application.NLP;
+import ai.djl.engine.Engine;
+import ai.djl.repository.Repository;
+import ai.djl.repository.Version;
+import ai.djl.repository.VersionRange;
+import ai.djl.repository.zoo.ModelZoo;
+import ai.djl.util.JsonUtils;
+import ai.djl.util.Utils;
+
+import com.google.gson.reflect.TypeToken;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.Type;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.GZIPInputStream;
+
+/** HfModelZoo is a repository that contains HuggingFace models. */
+public class HfModelZoo extends ModelZoo {
+
+    private static final Logger logger = LoggerFactory.getLogger(HfModelZoo.class);
+
+    private static final String REPO = "https://mlrepo.djl.ai/";
+    private static final Repository REPOSITORY = Repository.newInstance("Huggingface", REPO);
+    private static final String GROUP_ID = "ai.djl.huggingface.pytorch";
+
+    private static final long ONE_DAY = Duration.ofDays(1).toMillis();
+
+    HfModelZoo() {
+        Version version = new Version(Engine.class.getPackage().getSpecificationVersion());
+        addModels(NLP.FILL_MASK, version);
+        addModels(NLP.QUESTION_ANSWER, version);
+        addModels(NLP.TEXT_CLASSIFICATION, version);
+        addModels(NLP.TEXT_EMBEDDING, version);
+        addModels(NLP.TOKEN_CLASSIFICATION, version);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getGroupId() {
+        return GROUP_ID;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Set<String> getSupportedEngines() {
+        return Collections.singleton("PyTorch");
+    }
+
+    private void addModels(Application app, Version version) {
+        Map<String, Map<String, Object>> map = listModels(app);
+        for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) {
+            Map<String, Object> model = entry.getValue();
+            if ("failed".equals(model.get("result"))) {
+                continue;
+            }
+            String requires = (String) model.get("requires");
+            if (requires != null) {
+                // the model requires specific DJL version
+                VersionRange range = VersionRange.parse(requires);
+                if (!range.contains(version)) {
+                    continue;
+                }
+            }
+            String artifactId = entry.getKey();
+            addModel(REPOSITORY.model(app, GROUP_ID, artifactId, "0.0.1"));
+        }
+    }
+
+    private Map<String, Map<String, Object>> listModels(Application app) {
+        try {
+            String path = "model/" + app.getPath() + "/ai/djl/huggingface/pytorch/";
+            Path dir = Utils.getCacheDir().resolve("cache/repo/" + path);
+            if (Files.notExists(dir)) {
+                Files.createDirectories(dir);
+            } else if (!Files.isDirectory(dir)) {
+                logger.warn("Failed initialize cache directory: " + dir);
+                return Collections.emptyMap();
+            }
+            Type type = new TypeToken<Map<String, Map<String, Object>>>() {}.getType();
+
+            Path file = dir.resolve("models.json");
+            if (Files.exists(file)) {
+                long lastModified = Files.getLastModifiedTime(file).toMillis();
+                if (Boolean.getBoolean("offline")
+                        || System.currentTimeMillis() - lastModified < ONE_DAY) {
+                    try (Reader reader = Files.newBufferedReader(file)) {
+                        return JsonUtils.GSON.fromJson(reader, type);
+                    }
+                }
+            }
+
+            String url = REPO + path + "models.json.gz";
+            Path tmp = Files.createTempFile(dir, "models", ".tmp");
+            try (GZIPInputStream gis = new GZIPInputStream(new URL(url).openStream())) {
+                String json = Utils.toString(gis);
+                try (Writer writer = Files.newBufferedWriter(tmp)) {
+                    writer.write(json);
+                }
+                Utils.moveQuietly(tmp, file);
+                return JsonUtils.GSON.fromJson(json, type);
+            } finally {
+                Utils.deleteQuietly(tmp);
+            }
+        } catch (IOException e) {
+            logger.warn("Failed load index of models: " + app, e);
+        }
+
+        return Collections.emptyMap();
+    }
+}
diff --git a/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/HfZooProvider.java b/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/HfZooProvider.java
new file mode 100644
index 000000000..1f31f714e
--- /dev/null
+++ b/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/HfZooProvider.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
+ * with the License. A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+package ai.djl.huggingface.zoo;
+
+import ai.djl.repository.zoo.ModelZoo;
+import ai.djl.repository.zoo.ZooProvider;
+
+/**
+ * An Huggingface model zoo provider implements the {@link ai.djl.repository.zoo.ZooProvider}
+ * interface.
+ */
+public class HfZooProvider implements ZooProvider {
+
+    /** {@inheritDoc} */
+    @Override
+    public ModelZoo getModelZoo() {
+        return new HfModelZoo();
+    }
+}
diff --git a/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/package-info.java b/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/package-info.java
new file mode 100644
index 000000000..20149d707
--- /dev/null
+++ b/extensions/tokenizers/src/main/java/ai/djl/huggingface/zoo/package-info.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
+ * with the License. A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+/** Contains the built-in {@link ai.djl.huggingface.zoo.HfModelZoo}. */
+package ai.djl.huggingface.zoo;
diff --git a/extensions/tokenizers/src/main/resources/.empty b/extensions/tokenizers/src/main/resources/.empty
deleted file mode 100644
index e69de29bb..000000000
diff --git a/extensions/tokenizers/src/main/resources/META-INF/services/ai.djl.repository.zoo.ZooProvider b/extensions/tokenizers/src/main/resources/META-INF/services/ai.djl.repository.zoo.ZooProvider
new file mode 100644
index 000000000..956e00dcf
--- /dev/null
+++ b/extensions/tokenizers/src/main/resources/META-INF/services/ai.djl.repository.zoo.ZooProvider
@@ -0,0 +1,1 @@
+ai.djl.huggingface.zoo.HfZooProvider
diff --git a/integration/src/main/java/ai/djl/integration/util/FileUtils.java b/integration/src/main/java/ai/djl/integration/util/FileUtils.java
deleted file mode 100644
index 21d34a9f2..000000000
--- a/integration/src/main/java/ai/djl/integration/util/FileUtils.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
- * with the License. A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0/
- *
- * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
- * OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
- * and limitations under the License.
- */
-package ai.djl.integration.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-
-public final class FileUtils {
-
-    private FileUtils() {}
-
-    public static void download(String source, Path destination, String fileName)
-            throws IOException {
-        URL url = new URL(source);
-        try (InputStream in = url.openStream()) {
-            if (!Files.exists(destination)) {
-                Files.createDirectories(destination);
-            }
-            Files.copy(in, destination.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
-        }
-    }
-}


Test patch:
diff --git a/extensions/tokenizers/src/test/java/ai/djl/huggingface/zoo/ModelZooTest.java b/extensions/tokenizers/src/test/java/ai/djl/huggingface/zoo/ModelZooTest.java
new file mode 100644
index 000000000..ea9a5ca1b
--- /dev/null
+++ b/extensions/tokenizers/src/test/java/ai/djl/huggingface/zoo/ModelZooTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
+ * with the License. A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+package ai.djl.huggingface.zoo;
+
+import ai.djl.Application.NLP;
+import ai.djl.ModelException;
+import ai.djl.inference.Predictor;
+import ai.djl.modality.nlp.qa.QAInput;
+import ai.djl.repository.zoo.Criteria;
+import ai.djl.repository.zoo.ZooModel;
+import ai.djl.testing.TestRequirements;
+import ai.djl.translate.TranslateException;
+import ai.djl.util.JsonUtils;
+import ai.djl.util.Utils;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ModelZooTest {
+
+    @Test
+    public void testModelZoo() throws ModelException, IOException, TranslateException {
+        TestRequirements.nightly();
+
+        String question = "When did BBC Japan start broadcasting?";
+        String paragraph =
+                "BBC Japan was a general entertainment Channel. "
+                        + "Which operated between December 2004 and April 2006. "
+                        + "It ceased operations after its Japanese distributor folded.";
+
+        String url = "djl://ai.djl.huggingface.pytorch/deepset/minilm-uncased-squad2";
+        Criteria<QAInput, String> criteria =
+                Criteria.builder().setTypes(QAInput.class, String.class).optModelUrls(url).build();
+
+        try (ZooModel<QAInput, String> model = criteria.loadModel();
+                Predictor<QAInput, String> predictor = model.newPredictor()) {
+            QAInput input = new QAInput(question, paragraph);
+            String res = predictor.predict(input);
+            Assert.assertEquals(res, "december 2004");
+        }
+    }
+
+    @Test
+    public void testFutureVersion() throws IOException {
+        Map<String, Map<String, Object>> map = new ConcurrentHashMap<>();
+        Map<String, Object> model = new ConcurrentHashMap<>();
+        model.put("result", "failed");
+        map.put("model1", model);
+
+        model = new ConcurrentHashMap<>();
+        model.put("requires", "10.100.0+");
+        map.put("model2", model);
+
+        model = new ConcurrentHashMap<>();
+        model.put("requires", "0.19.0+");
+        map.put("model3", model);
+        map.put("model4", new ConcurrentHashMap<>());
+
+        String path = "model/" + NLP.QUESTION_ANSWER.getPath() + "/ai/djl/huggingface/pytorch/";
+        Path dir = Utils.getCacheDir().resolve("cache/repo/" + path);
+        Files.createDirectories(dir);
+        Path file = dir.resolve("models.json");
+        try (Writer writer = Files.newBufferedWriter(file)) {
+            writer.write(JsonUtils.GSON_PRETTY.toJson(map));
+        }
+        HfModelZoo zoo = new HfModelZoo();
+
+        Assert.assertNull(zoo.getModelLoader("model1"));
+        Assert.assertNull(zoo.getModelLoader("model2"));
+        Assert.assertNull(zoo.getModelLoader("model3"));
+        Assert.assertNotNull(zoo.getModelLoader("model4"));
+
+        Utils.deleteQuietly(file);
+    }
+}
diff --git a/extensions/tokenizers/src/test/java/ai/djl/huggingface/zoo/package-info.java b/extensions/tokenizers/src/test/java/ai/djl/huggingface/zoo/package-info.java
new file mode 100644
index 000000000..85d08046c
--- /dev/null
+++ b/extensions/tokenizers/src/test/java/ai/djl/huggingface/zoo/package-info.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
+ * with the License. A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+package ai.djl.huggingface.zoo;