/quarkus-snakejar

Quarkus extension that integrates SnakeJar Java library with embedded CPython to Quarkus

Primary LanguageJavaApache License 2.0Apache-2.0

quarkus-snakejar

Quarkus extension that integrates SnakeJar Java library with embedded CPython to Quarkus

This Quarkus extension enables calling Python native code from Quarkus REST services.

<dependency>
  <groupId>com.dropchop.quarkus</groupId>
  <artifactId>quarkus-snakejar</artifactId>
  <version>1.0.13</version>
</dependency>

Example

Complete example can be found in snakejar-example sub project.

REST Endpoint

@Path("/hello")
public class GreetingResource {
  private static final Logger LOG = LoggerFactory.getLogger(GreetingResource.class);

  @Inject
  LanguageDetectionService service;

  @GET
  @Produces(MediaType.TEXT_PLAIN)
  @Path("/lang_id")
  public String greeting(@QueryParam("text") String name) {
    try {
      Map<String, Double> lang = service.detectLanguage(name, 1);
      if (lang.isEmpty()) {
        return "EMPTY";
      }
      return lang.entrySet().iterator().next().getKey();
    } catch (Exception e) {
      LOG.warn("Got exception!", e);
      return "ERROR";
    }
  }
}

Service

@ApplicationScoped
public class LanguageDetectionService {

  public static class InvokeLangIdClass extends InvokeClass<HashMap<String, Double>> {
    @SuppressWarnings("unchecked")
    public InvokeLangIdClass() {
      super("lang_detect", "lang_id", "LanguageDetect", (Class<HashMap<String, Double>>)(Class<?>)HashMap.class);
    }
  }

  public static final Invocation<HashMap<String, Double>> LANG_ID_CLASS = new InvokeLangIdClass();

  @Inject
  Invoker invoker;

  public Map<String, Double> detectLanguage(String text, int numRet) throws Exception {
    Map<String, Double> result = invoker.apply(LANG_ID_CLASS,
    () -> new Object[]{
      text,
      numRet
    }).get();
    return result;
  }
}

application.properties

quarkus.log.level=INFO
quarkus.log.category."com.dropchop.quarkus.snakejar".min-level=TRACE
quarkus.log.category."com.dropchop.quarkus.snakejar".level=TRACE
quarkus.log.category."com.dropchop.snakejar".min-level=TRACE
quarkus.log.category."com.dropchop.snakejar".level=INFO

quarkus.native.resources.includes=*.py

quarkus.snakejar.module-order=lang_detect_model,lang_detect
quarkus.snakejar.modules.lang_detect_model.source=classpath://lang_detect_model.py
quarkus.snakejar.modules.lang_detect.source=classpath://lang_detect.py

Python script from class path (that does actual language detection):

from lang_detect_model import LanguageDetectModel


class LanguageDetect:

    @staticmethod
    def lang_id(text: str, num_ret: int = 1):
        fasttext_model = LanguageDetectModel.get_model()
        classification, confidence = fasttext_model.predict(text.replace("\n", " "), k=num_ret)
        result = {}
        for idx, val in enumerate(classification):
            new_label = classification[idx]
            result[new_label] = confidence[idx]
        return result
        

Python script from class path (that provides Fasttext model for language detection):

import os
import fasttext

class LanguageDetectModel:

    fasttext_model = None

    @staticmethod
    def get_model():
        if not LanguageDetectModel.fasttext_model:
            path = os.path.normpath(
                os.path.join(
                    os.path.dirname(__file__), 
                    'lid.176.ftz.wiki.fasttext'))
            LanguageDetectModel.fasttext_model = fasttext.load_model(path)
        return LanguageDetectModel.fasttext_model