diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 753e361..14fc77a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 - uses: actions/setup-java@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v4 with: - java-version: 11 + java-version: 17 distribution: 'temurin' cache: maven - name: Build with Maven diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 28f8971..adca6aa 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,10 +12,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 - uses: actions/setup-java@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v4 with: - java-version: 11 + java-version: 17 distribution: 'temurin' - name: Build with Maven run: mvn -B package --file pom.xml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d3003f2..9a0564b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,10 +18,10 @@ jobs: - uses: actions/checkout@v3 with: ref: ${{ github.event.inputs.tag }} - - name: Set up JDK 11 - uses: actions/setup-java@v1 + - name: Set up JDK 17 + uses: actions/setup-java@v4 with: - java-version: 11 + java-version: 17 distribution: 'temurin' - name: Build with Maven run: mvn -B package --file pom.xml diff --git a/djl-spring-boot-console-sample/pom.xml b/djl-spring-boot-console-sample/pom.xml index 6f1ecbd..e07fb19 100644 --- a/djl-spring-boot-console-sample/pom.xml +++ b/djl-spring-boot-console-sample/pom.xml @@ -5,12 +5,12 @@ spring-boot-starter-parent org.springframework.boot - 2.7.3 + 3.2.1 ai.djl.spring.examples djl-spring-boot-console-sample - 0.23-SNAPSHOT + 0.26-SNAPSHOT 11 @@ -20,12 +20,12 @@ ai.djl.spring djl-spring-boot-starter-autoconfigure - 0.23-SNAPSHOT + 0.26-SNAPSHOT ai.djl.spring djl-spring-boot-starter-pytorch-auto - 0.23-SNAPSHOT + 0.26-SNAPSHOT diff --git a/djl-spring-boot-console-sample/src/main/java/ai/djl/spring/examples/console/ConsoleApplication.java b/djl-spring-boot-console-sample/src/main/java/ai/djl/spring/examples/console/ConsoleApplication.java index 63bec39..041770f 100644 --- a/djl-spring-boot-console-sample/src/main/java/ai/djl/spring/examples/console/ConsoleApplication.java +++ b/djl-spring-boot-console-sample/src/main/java/ai/djl/spring/examples/console/ConsoleApplication.java @@ -13,11 +13,11 @@ package ai.djl.spring.examples.console; import ai.djl.inference.Predictor; - import ai.djl.modality.Classifications; import ai.djl.modality.cv.Image; import ai.djl.modality.cv.ImageFactory; import ai.djl.modality.cv.output.DetectedObjects; +import jakarta.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -26,7 +26,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.core.io.ClassPathResource; -import javax.annotation.Resource; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; diff --git a/djl-spring-boot-starter-autoconfigure/pom.xml b/djl-spring-boot-starter-autoconfigure/pom.xml index 69475bc..e11d8e6 100644 --- a/djl-spring-boot-starter-autoconfigure/pom.xml +++ b/djl-spring-boot-starter-autoconfigure/pom.xml @@ -4,11 +4,11 @@ ai.djl.spring djl-spring-boot-starter-parent - 0.23-SNAPSHOT + 0.26-SNAPSHOT ../djl-spring-boot-starter-parent djl-spring-boot-starter-autoconfigure - 0.23-SNAPSHOT + 0.26-SNAPSHOT djl-spring-boot-starter-autoconfigure DJL Spring Boot starter project @@ -27,7 +27,7 @@ ai.djl.spring djl-spring-boot-starter-mxnet-auto - 0.23-SNAPSHOT + 0.26-SNAPSHOT test diff --git a/djl-spring-boot-starter-autoconfigure/src/main/java/ai/djl/spring/configuration/DjlAutoConfiguration.java b/djl-spring-boot-starter-autoconfigure/src/main/java/ai/djl/spring/configuration/DjlAutoConfiguration.java index ed7acbf..bf8eca2 100644 --- a/djl-spring-boot-starter-autoconfigure/src/main/java/ai/djl/spring/configuration/DjlAutoConfiguration.java +++ b/djl-spring-boot-starter-autoconfigure/src/main/java/ai/djl/spring/configuration/DjlAutoConfiguration.java @@ -12,6 +12,9 @@ */ package ai.djl.spring.configuration; +import java.io.IOException; +import java.util.function.Supplier; + import ai.djl.MalformedModelException; import ai.djl.inference.Predictor; import ai.djl.modality.cv.Image; @@ -20,21 +23,20 @@ import ai.djl.repository.zoo.ModelNotFoundException; import ai.djl.repository.zoo.ModelZoo; import ai.djl.repository.zoo.ZooModel; +import ai.djl.training.util.ProgressBar; import ai.djl.translate.TranslatorFactory; import ai.djl.util.ClassLoaderUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; - -import java.io.IOException; -import java.util.function.Supplier; @Configuration @ConditionalOnMissingBean(ZooModel.class) @@ -87,6 +89,18 @@ public class DjlAutoConfiguration { if(urls != null && urls.length > 0) { builder.optModelUrls(StringUtils.arrayToCommaDelimitedString(urls)); } + if (properties.isProgress()) { + builder.optProgress(new ProgressBar()); + } + if (StringUtils.hasText(properties.getModelName())) { + builder.optModelName(properties.getModelName()); + } + if (StringUtils.hasText(properties.getGroupId())) { + builder.optGroupId(properties.getGroupId()); + } + if (StringUtils.hasText(properties.getEngine())) { + builder.optEngine(properties.getEngine()); + } try { var zooModel = builder.build().loadModel(); diff --git a/djl-spring-boot-starter-autoconfigure/src/main/java/ai/djl/spring/configuration/DjlConfigurationProperties.java b/djl-spring-boot-starter-autoconfigure/src/main/java/ai/djl/spring/configuration/DjlConfigurationProperties.java index cb2397f..095c4ce 100644 --- a/djl-spring-boot-starter-autoconfigure/src/main/java/ai/djl/spring/configuration/DjlConfigurationProperties.java +++ b/djl-spring-boot-starter-autoconfigure/src/main/java/ai/djl/spring/configuration/DjlConfigurationProperties.java @@ -72,6 +72,30 @@ public class DjlConfigurationProperties { */ private Map modelFilter; + + /** + * Supported engine names: * https://docs.djl.ai/docs/engine.html#supported-engines + * Possible values are: MXNet, PyTorch, TensorFlow, TFLite, OnnxRuntime, PaddlePaddle, TensorRT + */ + private String engine; + + /** + * Defines the groupId of the model to be loaded. + */ + private String groupId; + + /** + * Defines the modelName of the model to be loaded. + * Leave it empty if you want to load the latest version of the model. + * Use "saved_model" for TensorFlow saved models. + */ + private String modelName; + + /** + * Defines whether to show progress bar when loading the model. + */ + private boolean progress = true; + public Map getModelFilter() { return modelFilter; } @@ -135,4 +159,36 @@ public String getTranslatorFactory() { public void setTranslatorFactory(String translatorFactory) { this.translatorFactory = translatorFactory; } + + public String getEngine() { + return engine; + } + + public void setEngine(String engine) { + this.engine = engine; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getModelName() { + return modelName; + } + + public void setModelName(String modelName) { + this.modelName = modelName; + } + + public boolean isProgress() { + return progress; + } + + public void setProgress(boolean progress) { + this.progress = progress; + } } diff --git a/djl-spring-boot-starter-mxnet-auto/pom.xml b/djl-spring-boot-starter-mxnet-auto/pom.xml index a70fa20..cf1a6ea 100644 --- a/djl-spring-boot-starter-mxnet-auto/pom.xml +++ b/djl-spring-boot-starter-mxnet-auto/pom.xml @@ -4,7 +4,7 @@ ai.djl.spring djl-spring-boot-starter-parent - 0.23-SNAPSHOT + 0.26-SNAPSHOT ../djl-spring-boot-starter-parent djl-spring-boot-starter-mxnet-auto diff --git a/djl-spring-boot-starter-mxnet-linux-x86_64/pom.xml b/djl-spring-boot-starter-mxnet-linux-x86_64/pom.xml index c3847ff..7ae962f 100644 --- a/djl-spring-boot-starter-mxnet-linux-x86_64/pom.xml +++ b/djl-spring-boot-starter-mxnet-linux-x86_64/pom.xml @@ -4,7 +4,7 @@ ai.djl.spring djl-spring-boot-starter-parent - 0.23-SNAPSHOT + 0.26-SNAPSHOT ../djl-spring-boot-starter-parent djl-spring-boot-starter-mxnet-linux-x86_64 diff --git a/djl-spring-boot-starter-mxnet-osx-x86_64/pom.xml b/djl-spring-boot-starter-mxnet-osx-x86_64/pom.xml index 41de56e..cb20a6f 100644 --- a/djl-spring-boot-starter-mxnet-osx-x86_64/pom.xml +++ b/djl-spring-boot-starter-mxnet-osx-x86_64/pom.xml @@ -4,7 +4,7 @@ ai.djl.spring djl-spring-boot-starter-parent - 0.23-SNAPSHOT + 0.26-SNAPSHOT ../djl-spring-boot-starter-parent djl-spring-boot-starter-mxnet-osx-x86_64 diff --git a/djl-spring-boot-starter-parent/pom.xml b/djl-spring-boot-starter-parent/pom.xml index 33bf725..b4a8fba 100644 --- a/djl-spring-boot-starter-parent/pom.xml +++ b/djl-spring-boot-starter-parent/pom.xml @@ -4,13 +4,13 @@ org.springframework.boot spring-boot-starter-parent - 2.7.3 + 3.2.1 ai.djl.spring djl-spring-boot-starter-parent - 0.23-SNAPSHOT + 0.26-SNAPSHOT djl-spring-boot-starter-parent DJL starter project for Spring Boot pom @@ -34,7 +34,7 @@ - 0.23.0 + 0.26.0 11 3.1.1 3.1.0 diff --git a/djl-spring-boot-starter-pytorch-auto/pom.xml b/djl-spring-boot-starter-pytorch-auto/pom.xml index d14abc6..6b0565e 100644 --- a/djl-spring-boot-starter-pytorch-auto/pom.xml +++ b/djl-spring-boot-starter-pytorch-auto/pom.xml @@ -4,7 +4,7 @@ ai.djl.spring djl-spring-boot-starter-parent - 0.23-SNAPSHOT + 0.26-SNAPSHOT ../djl-spring-boot-starter-parent djl-spring-boot-starter-pytorch-auto diff --git a/djl-spring-boot-starter-tensorflow-auto/pom.xml b/djl-spring-boot-starter-tensorflow-auto/pom.xml index 2eba310..4ca56d9 100644 --- a/djl-spring-boot-starter-tensorflow-auto/pom.xml +++ b/djl-spring-boot-starter-tensorflow-auto/pom.xml @@ -4,7 +4,7 @@ ai.djl.spring djl-spring-boot-starter-parent - 0.23-SNAPSHOT + 0.26-SNAPSHOT ../djl-spring-boot-starter-parent djl-spring-boot-starter-tensorflow-auto diff --git a/docs/walkthrough/getting-started.html b/docs/walkthrough/getting-started.html index aeb4eea..d0e1b1e 100644 --- a/docs/walkthrough/getting-started.html +++ b/docs/walkthrough/getting-started.html @@ -170,7 +170,7 @@

4. Simple Application Walkthrough

> ../mvnw spring-boot:run

Alternatively you can run it directly with java -jar command:

-
java -jar target/djl-spring-boot-console-sample-0.23-SNAPSHOT.jar +
java -jar target/djl-spring-boot-console-sample-0.26-SNAPSHOT.jar

5. More Complex Application Example

Code Examples based on REST API example leveraging DJL Spring Boot Starter demonstrates a RESTful API that can take images from Amazon S3 bucket and stores the object detection results back in S3. This API represents a microservice capable of taking any image reference (uploaded to the predefined Amazon S3 bucket) and run object detection on it. This API could be leveraged directly through REST API clients like Postman, or within a mobile or web application.

diff --git a/docs/walkthrough/getting-started.md b/docs/walkthrough/getting-started.md index 42c9c6d..5d50917 100644 --- a/docs/walkthrough/getting-started.md +++ b/docs/walkthrough/getting-started.md @@ -1,20 +1,20 @@ **Work in progress** -## Abstract +## Abstract *Many AWS customers (startups and large enterprises) are on their path to adopt machine learning and deep learning in their existing applications. The reasons for machine learning adoption are dictated by the pace of innovation in the industry and business use cases range from customer service (including object detection from images and video streams, sentiment analysis) to fraud detection and collaboration. However, until recently, the adoption path was quite steep and required development of internal technical expertise in new programming languages (e.g. python) and frameworks with cascading effect on the whole software development life-cycle, including coding, building, testing, deployment. The approach outlined in this blog post enables enterprises to leverage existing talent and resources (frameworks, pipelines, deployments) to integrate machine learning capabilities.* ## 1. Introduction -Spring boot, one of the most popular and wide-spread frameworks for microservices development, has simplified implementation of distributed systems. Despite its broad appeal, there are few options to easily integrate Machine Learning (ML) natively in Java. Existing solutions such as stock APIs often do not meet customized application requirements, and developing customized solutions is time consuming and not cost-effective. +Spring boot, one of the most popular and wide-spread frameworks for microservices development, has simplified implementation of distributed systems. Despite its broad appeal, there are few options to easily integrate Machine Learning (ML) natively in Java. Existing solutions such as stock APIs often do not meet customized application requirements, and developing customized solutions is time consuming and not cost-effective. -There are a number of ways how developers approached integration of machine learning capabilities in existing applications. Let’s take inference for example: current options vary from using stock API to having a Python or C++ based application wrapped with an API for remote calls. However, stock API while having robust models may not quite fit your domain or industry, causing defects discovered in production with few options to address them. In other cases, when running inference at scale (for example in streaming applications as well as latency sensitive microservices) making a remote call may not be a viable option due to performance reasons. +There are a number of ways how developers approached integration of machine learning capabilities in existing applications. Let’s take inference for example: current options vary from using stock API to having a Python or C++ based application wrapped with an API for remote calls. However, stock API while having robust models may not quite fit your domain or industry, causing defects discovered in production with few options to address them. In other cases, when running inference at scale (for example in streaming applications as well as latency sensitive microservices) making a remote call may not be a viable option due to performance reasons. Recognizing this challenge, we at AWS have created a few open-source projects to facilitate adoption of ML for Java and microservices and ultimately help our customers, partners and the open source community as a whole. These initiatives align closely with the AWS goal to take technology that was traditionally cost-prohibitive and difficult for many organizations to adopt, and make it accessible to a much broader audience. In this blog post we will demonstrate how Java users can integrate ML into their Spring applications with Spring - Boot Starter for Deep Java Library (DJL). + Boot Starter for Deep Java Library (DJL). Together we will review how to apply these frameworks in action and integrate ML capabilities in a microservice, demonstrating common deep learning use cases around object detection and classification. @@ -24,7 +24,7 @@ Deep Java Library (DJL) is an open-source, high-level, framework-agnostic Java A DJL provides a convenient abstraction layer to use the most popular AI/ML frameworks such as MXNet, PyTorch and TensorFlow. However, it is not just a convenience on top of the existing libraries some of which provide Java API / bindings. With DJL API you are getting a uniform and consistent layer that can interact with all of these frameworks, allowing to swap out the framework of choice without any impact to the client code. -This unique features in combination with a fairly rich model zoo repository (repository with pre-trained models), can enable ML engineers to find optimal models for the task at hand regardless of the underlying model implementation. +This unique features in combination with a fairly rich model zoo repository (repository with pre-trained models), can enable ML engineers to find optimal models for the task at hand regardless of the underlying model implementation. For more information on DJL please refer to the [DJL GitHub Repository](https://github.com/deepjavalibrary/djl/) and [FAQ](https://github.com/deepjavalibrary/djl/blob/master/docs/faq.md). @@ -33,15 +33,15 @@ For more information on DJL please refer to the [DJL GitHub Repository](https:/ What is Spring Boot Starter (or custom starter)? Spring Boot Starter is a one-stop shop for all the Spring and related technologies that you need without having to hunt through sample code and copy-paste loads of dependency descriptors. Please see the [official Spring Boot documentation](https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/#using-boot-starter) for more information on the starters. -Following this definition, DJL Spring Boot Starter provides all the dependencies required to start using DJL in Spring as a single artifact. In addition to the dependency management, starter includes an [auto-configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-developing-auto-configuration) that allows to automatically wire dependencies based on the configuration file supplied by the user and make them available as beans in the Spring Application context. +Following this definition, DJL Spring Boot Starter provides all the dependencies required to start using DJL in Spring as a single artifact. In addition to the dependency management, starter includes an [auto-configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-developing-auto-configuration) that allows to automatically wire dependencies based on the configuration file supplied by the user and make them available as beans in the Spring Application context. ### 3.1 Dependency Management -DJL library is platform specific, however it provides ways to automatically look up correct dependency based on the target OS. Along with that, DJL may be configured with different underlying engines, such as MXNet, PyTorch and TensorFlow, so the user is expected to make this choice before the starter is used. However, even after the choice is made, the underlying engine (as well as the target OS archticture) can be changed by just changing your maven (or gradle) dependency with no impact to your code. +DJL library is platform specific, however it provides ways to automatically look up correct dependency based on the target OS. Along with that, DJL may be configured with different underlying engines, such as MXNet, PyTorch and TensorFlow, so the user is expected to make this choice before the starter is used. However, even after the choice is made, the underlying engine (as well as the target OS archticture) can be changed by just changing your maven (or gradle) dependency with no impact to your code. The starter dependency management is organized in a way that provides most flexibility to the user. - -For MXNet starter the following OS classifiers are supported: `osx-x86_64` for Mac OSX, `linux-x86_64` for generic linux, `win-x86_64` for Windows distributions and `auto` for automatic detection of the target OS. The last option requires connectivity to the external artifact repository (e.g. Maven Central) at runtime, which may be an issue for systems with restricted egress. + +For MXNet starter the following OS classifiers are supported: `osx-x86_64` for Mac OSX, `linux-x86_64` for generic linux, `win-x86_64` for Windows distributions and `auto` for automatic detection of the target OS. The last option requires connectivity to the external artifact repository (e.g. Maven Central) at runtime, which may be an issue for systems with restricted egress. Below you can see an example of *MXNet Dependency for linux architecture*, which is optimal for container workloads: @@ -49,13 +49,13 @@ Below you can see an example of *MXNet Dependency for linux architecture*, which spring-boot-starter-parent org.springframework.boot - 2.2.6.RELEASE + 3.2.1 11 5.3.0 - + ai.djl.spring @@ -103,12 +103,12 @@ Gradle dependencies will look similar. It is important to set the JNA version as ### 3.2 Spring Auto-configuration - Once dependencies are configured correctly in your Spring Boot application, the next step is to configure your beans and wire them properly for injection. It is fairly easy to configure DJL related beans and make them available in the Spring application context, but it requires internal knowledge of the library as well as peculiarities of individual classes for proper scoping, since some beans are thread-safe, others should be scoped per request/thread. To assist with this configuration, the DJL Spring Boot starter provides an [auto-configuration](https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/html/using-spring-boot.html#using-boot-auto-configuration). - + Once dependencies are configured correctly in your Spring Boot application, the next step is to configure your beans and wire them properly for injection. It is fairly easy to configure DJL related beans and make them available in the Spring application context, but it requires internal knowledge of the library as well as peculiarities of individual classes for proper scoping, since some beans are thread-safe, others should be scoped per request/thread. To assist with this configuration, the DJL Spring Boot starter provides an [auto-configuration](https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/html/using-spring-boot.html#using-boot-auto-configuration). + This component is separate from the dependency component and requires an explicit dependency. It is done for a couple of reasons: 1. Some developers prefer full control over the configuration options and may be opposed to the Spring "auto magic". In such cases, the starter will support just basic set of dependencies and allow developers to wire components explicitly. - 2. Auto-configuration component is generic for all kinds of the DJL configuration. Regardless of the underlying target OS or the actual engine, the configuration component remains the same. So using the same auto-configuration, developers can swap underlying dependencies as a single step operation without any impact to the code. + 2. Auto-configuration component is generic for all kinds of the DJL configuration. Regardless of the underlying target OS or the actual engine, the configuration component remains the same. So using the same auto-configuration, developers can swap underlying dependencies as a single step operation without any impact to the code. Declaring dependency on auto-configuration in maven: @@ -128,7 +128,7 @@ Or in gradle `build.gradle.kts`: } ``` -Once the dependency is declared, the Spring Boot framework will automatically locate the configuration and wire the required components. At present, for inference it will look up the model from the model zoo and create a predictor that will be readily available to run inference. +Once the dependency is declared, the Spring Boot framework will automatically locate the configuration and wire the required components. At present, for inference it will look up the model from the model zoo and create a predictor that will be readily available to run inference. Users are expected to supply standard Spring configuration (`application.yml` or `application.properties`) specifying their application type and model filter parameters to look up the proper model to use: @@ -143,9 +143,9 @@ Users are expected to supply standard Spring configuration (`application.yml` or SEMANTIC_SEGMENTATION(CV.SEMANTIC_SEGMENTATION); ``` -For example, in order to run object detection in images, user can set the application type to `OBJECT_DETECTION`. DJL related configuration should be namespaced under `djl` for example `djl.application-type=OBJECT_DETECTION` if `application.properties` is used. +For example, in order to run object detection in images, user can set the application type to `OBJECT_DETECTION`. DJL related configuration should be namespaced under `djl` for example `djl.application-type=OBJECT_DETECTION` if `application.properties` is used. -Example of `yaml` configuration for DJL auto-configuration : +Example of `yaml` configuration for DJL auto-configuration : ```yaml djl: @@ -168,17 +168,17 @@ Example of `yaml` configuration for DJL auto-configuration Configuration creation does not have to be fully manual and DJL Spring Boot Starter provides configuration content assistant for most IDEs with the help of Spring IDE plugins (tested on IntelliJ IDEA, but expected to work in Eclipse with STS and NetBeans IDE). -For IntelliJ you can use `Ctrl+Space` for auto-completion and `Ctrl+J` for quick doc on any property. +For IntelliJ you can use `Ctrl+Space` for auto-completion and `Ctrl+J` for quick doc on any property. + + - - ## 4. Simple Application Walkthrough Code Example based on [Simple Spring Boot Application](https://github.com/deepjavalibrary/djl-spring-boot-starter/tree/master/djl-spring-boot-console-sample) demonstrate single shot object detection with DJL and MXNet. Dependencies setup are per [maven dependency section](#maven-auto-dependency). Configuration setup is identical to the [`application.yml` in the example](#yaml-example). -The application is a regular console Spring Boot application with a single class (note that no other code is required). +The application is a regular console Spring Boot application with a single class (note that no other code is required). **Injecting predictor for object detection** @@ -186,7 +186,7 @@ The application is a regular console Spring Boot application with a single class @Resource private Supplier> predictorProvider; ``` -It is recommended to use predictor in a `try-with-resources` block to make sure it is closed after each use, hence the supplier of predictor is injected for convenient instantiation. +It is recommended to use predictor in a `try-with-resources` block to make sure it is closed after each use, hence the supplier of predictor is injected for convenient instantiation. **Running object detection** @@ -212,7 +212,7 @@ The above code will run object detection on the supplied image (expected to be o Assuming you have checked out the repository and are now in the root of the repository: ```bash - > git clone git@github.com:deepjavalibrary/djl-spring-boot-starter.git + > git clone git@github.com:deepjavalibrary/djl-spring-boot-starter.git > cd djl-spring-boot-starter/djl-spring-boot-console-sample > ../mvnw package > ../mvnw spring-boot:run @@ -221,16 +221,16 @@ Assuming you have checked out the repository and are now in the root of the repo Alternatively you can run it directly with `java -jar` command: ``` - java -jar target/djl-spring-boot-console-sample-0.23-SNAPSHOT.jar + java -jar target/djl-spring-boot-console-sample-0.26-SNAPSHOT.jar ``` -## 5. More Complex Application Example +## 5. More Complex Application Example -Code Examples based on [REST API example leveraging DJL Spring Boot Starter](https://github.com/deepjavalibrary/djl-spring-boot-starter-demo/tree/master/djl-spring-boot-app/) demonstrates a RESTful API that can take images from Amazon S3 bucket and stores the object detection results back in S3. This API represents a microservice capable of taking any image reference (uploaded to the predefined Amazon S3 bucket) and run object detection on it. This API could be leveraged directly through REST API clients like Postman, or within a mobile or web application. +Code Examples based on [REST API example leveraging DJL Spring Boot Starter](https://github.com/deepjavalibrary/djl-spring-boot-starter-demo/tree/master/djl-spring-boot-app/) demonstrates a RESTful API that can take images from Amazon S3 bucket and stores the object detection results back in S3. This API represents a microservice capable of taking any image reference (uploaded to the predefined Amazon S3 bucket) and run object detection on it. This API could be leveraged directly through REST API clients like Postman, or within a mobile or web application. The API portion is using gradle as its build system and leverages Spring MVC for REST API implementation. For simplicity, the controller is implemented as a blocking call. For high-volume production usage, it is recommended to use reactive style of API implementation such as WebFlux. It contains an example of an [explicit programmatic configuration](https://github.com/deepjavalibrary/djl-spring-boot-starter-demo/blob/master/djl-spring-boot-app/src/main/java/com/aws/samples/djlspringboot/InferenceConfiguration.java) of DJL components in your Spring Boot Application. -The web application portion is implemented as a Kotlin Spring MVC application with a reactive REST API client to invoke the backend API. +The web application portion is implemented as a Kotlin Spring MVC application with a reactive REST API client to invoke the backend API. The user is presented with a list of files and an option to select any file for upload and object detection, the API output is displayed directly below: @@ -239,18 +239,18 @@ The user is presented with a list of files and an option to select any file for The result of the object detection is applied back to the image, highlighting the areas where objects were detected and uploaded to S3: - -In subsequent posts, we will review how to containerize these applications and organize a full CI/CD pipeline deploying to Amazon Elastic Kubernetes Service. + +In subsequent posts, we will review how to containerize these applications and organize a full CI/CD pipeline deploying to Amazon Elastic Kubernetes Service. ## 6. Conclusion -Adopting machine learning with DJL and Spring Boot is a simple and powerful approach that enables customers to combine existing battle-tested microservice technology stack and the most proven deep learning frameworks like MXNet, PyTorch and Tensorflow through the convenient abstraction layers provided by DJL and Spring Boot. +Adopting machine learning with DJL and Spring Boot is a simple and powerful approach that enables customers to combine existing battle-tested microservice technology stack and the most proven deep learning frameworks like MXNet, PyTorch and Tensorflow through the convenient abstraction layers provided by DJL and Spring Boot. ## 7. References [DJL Spring Boot Starter](https://github.com/deepjavalibrary/djl-spring-boot-starter) - Spring Boot starter that allows Spring Boot developers to start using DJL for inference - + [DJL Spring Boot Demo](https://github.com/deepjavalibrary/djl-spring-boot-starter-demo) - Demo repository containing java API that leverages the starter and gradle as well as a small kotlin-based web application - -[DJL](https://github.com/deepjavalibrary/djl/) - DJL (Deep Java Library) main repository - + +[DJL](https://github.com/deepjavalibrary/djl/) - DJL (Deep Java Library) main repository + diff --git a/pom.xml b/pom.xml index bb7c86e..dc679d6 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 ai.djl.spring djl-spring-boot-starter-project - 0.23-SNAPSHOT + 0.26-SNAPSHOT djl-spring-boot-starter-project DJL starter project for Spring Boot pom