Quick Start

SMILE is a comprehensive, high-performance machine learning engine for the JVM. SMILE v7 requires Java 25. Besides Java, SMILE also provides idiomatic APIs for Scala and Kotlin. The core module is self-contained (no native dependencies required for most algorithms). Optionally, native BLAS/LAPACK libraries can be used for accelerated linear algebra, and LibTorch (PyTorch C++) enables GPU-accelerated deep learning and LLM inference.

Copy the snippet below to try SMILE in your own JVM project.

var iris = Read.arff("data/weka/iris.arff");
var formula = Formula.lhs("class");
var rf = RandomForest.fit(formula, iris);
System.out.println(rf.metrics());

Installation

Add the relevant artifact(s) to your build tool. All artifacts are published to Maven Central.


<!-- Core ML algorithms (classification, regression, clustering, …) -->
<dependency>
  <groupId>com.github.haifengl</groupId>
  <artifactId>smile-core</artifactId>
  <version>7.0.0</version>
</dependency>

<!-- Deep learning + LLMs (requires LibTorch native libraries) -->
<dependency>
  <groupId>com.github.haifengl</groupId>
  <artifactId>smile-deep</artifactId>
  <version>7.0.0</version>
</dependency>

<!-- Natural language processing -->
<dependency>
  <groupId>com.github.haifengl</groupId>
  <artifactId>smile-nlp</artifactId>
  <version>7.0.0</version>
</dependency>

<!-- Swing + Vega-Lite data visualization -->
<dependency>
  <groupId>com.github.haifengl</groupId>
  <artifactId>smile-plot</artifactId>
  <version>7.0.0</version>
</dependency>
            

Native BLAS / LAPACK (optional)

Several algorithms (manifold learning, Gaussian Process, MLP) benefit significantly from native BLAS/LAPACK. Install the system libraries:

Bash

sudo apt update
sudo apt install libopenblas-dev libarpack2
            
Bash

brew install arpack
# If macOS SIP strips DYLD_LIBRARY_PATH, copy the dylib to your working directory:
cp /opt/homebrew/lib/libarpack.dylib .
            

Pre-built DLLs are included in the bin/ directory of the release package. Add that directory to your PATH.

GPU / LibTorch (for Deep Learning & LLMs)

The smile-deep module calls LibTorch through Java's Foreign Function & Memory (FFM) API — not JNI — so native libraries are resolved via the platform loader (LD_LIBRARY_PATH on Linux, PATH on Windows), not java.library.path. On macOS, System Integrity Protection (SIP) strips DYLD_LIBRARY_PATH from most child processes; copy or symlink required .dylib files into your working directory or /usr/local/lib instead.

The release package bundles libsmile_torch and LibTorch under bin/ and libtorch/. GPU builds link LibTorch against a specific CUDA version — make sure your machine has a compatible NVIDIA driver and CUDA runtime libraries (cuDNN, etc.) before running GPU workloads. CPU-only inference works without a GPU.

Build from Source

Clone the repository and build with the Gradle wrapper (requires Java 25):

Bash

git clone https://github.com/haifengl/smile.git
cd smile
./gradlew build -x test        # build all modules, skip tests
./gradlew :core:build -x test  # build only the core module
    

To run the tests (requires LibTorch on the library path for smile-deep):

Bash

./gradlew :core:test
./gradlew :deep:test -DexcludeTags=integration
    

Download the Release Package

For the interactive shell and CLI tools, download the self-contained release package from the releases page. It works on macOS, Linux, and Windows.

Bash

# Extract and run first-time setup (BLAS/LAPACK, Python venv — see GPU / LibTorch above)
cd bin
./setup        # once: native libs + Python environment
./smile        # launches SMILE Studio (desktop notebook IDE)
    

Run bin/setup once after unzipping the release package. It installs optional native dependencies via your system package manager:

It also installs ripgrep, creates a Python virtual environment, and pulls packages from conf/requirements.txt (including ONNX Runtime). LibTorch and CUDA are not installed by setup — they ship with the release bundle (GPU builds) or must match your build environment when compiling from source.

Interactive Shell

SMILE integrates with JShell (available since Java 9). In the home directory of the release package, run:

Bash

$ ./smile shell
            

All SMILE classes are pre-imported. To pass more heap memory:

Bash

$ ./smile shell -R-Xmx30G
            

When the shell starts you will see the SMILE banner followed by the JShell prompt:

Java

|  Welcome to SMILE  -- Version 7.0.0
===============================================================================
|  Welcome to JShell -- Version 25
|  For an introduction type: /help intro

smile>
            

All SMILE definitions are pre-imported. You can run any valid Java expression. Type /exit to leave:

Java

smile> 2 + 3
$1 ==> 5

smile> var iris = Read.arff("data/weka/iris.arff")
iris ==> [...]

smile> var rf = RandomForest.fit(Formula.lhs("class"), iris)
smile> System.out.println(rf.metrics())
            

The Scala REPL has all high-level SMILE operators pre-imported:

Bash

$ ./smile scala
$ ./smile scala -J-Xmx30G   # with extra heap
            
Scala

smile> val iris = read.arff("data/weka/iris.arff")
smile> val rf   = randomForest("class" ~, iris)
smile> println(rf.metrics)

// Tab-completion shows available classifiers:
smile> smile.classification.r
randomForest   rbfnet   rda
            

There is no ./smile kotlin CLI REPL. For interactive Kotlin, use SMILE Studio (./smile) and open a .kts notebook — the release package includes notebooks/kotlin.ipynb as a starter. The idiomatic API comes from the smile-kotlin artifact:

Kotlin

val iris = read.arff("data/weka/iris.arff")
val rf   = randomForest(Formula.lhs("class"), iris)
println(rf.metrics())
            

Running a Script

Save a snippet and run it non-interactively with the matching shell:


// examples/iris.jsh
import smile.classification.RandomForest;
import smile.data.formula.Formula;
import smile.io.Read;

var data    = Read.arff("data/weka/iris.arff");
var formula = Formula.lhs("class");
var rf      = RandomForest.fit(formula, data);
System.out.println(rf.metrics());
            

$ ./smile shell examples/iris.jsh
            

Training & Inference CLI

The SMILE shell also exposes a command-line interface for training models, batch prediction, and real-time serving — no code required.

Train a Random Forest on the Iris dataset and save the model:

Bash

$ ./smile train \
    --data  data/weka/iris.arff \
    --formula "class ~ ." \
    --model iris_rf.sml \
    random-forest

Training metrics: {
  fit time: 191.678 ms,
  score time: 17.059 ms,
  validation data size: 150,
  error: 6,
  accuracy: 96.00%,
  cross entropy: 0.1316
}
            

Run ./smile train -h for a full list of supported algorithms (ada-boost, cart, gradient-boost, lasso, lda, logistic, mlp, ols, qda, random-forest, rbf, rda, ridge, svm, …) and ./smile train random-forest -h for algorithm-specific options.

Run batch inference on a file using a saved model:

Bash

$ ./smile predict \
    --model iris_rf.sml \
    --probability \
    data/weka/iris.arff

0 0.9601 0.0205 0.0194
0 0.9599 0.0206 0.0195
...
            

The optional --probability flag outputs posterior class probabilities alongside the predicted label.

Start an HTTP inference server (powered by Quarkus):

Bash

$ ./smile serve --model iris_rf.sml
INFO  Listening on: http://0.0.0.0:8080

# Query a single sample
$ curl -X POST http://localhost:8080/api/v1/models/iris_rf-1 \
       -H "Content-Type: application/json" \
       -d '{"sepallength":5.1,"sepalwidth":3.5,"petallength":1.4,"petalwidth":0.2}'

{"class":0,"probability":[0.9599,0.0207,0.0194]}
            

If --model points to a directory, every .sml file is loaded automatically. Discover available endpoints with GET /api/v1/models.

The /stream endpoint processes a JSON-lines or CSV request body element-by-element with full back-pressure, making it safe to send very large payloads (multi-GB):

Bash

# Generate 150,000 rows (iris × 1000) and stream them through the server
$ for i in {1..1000}; do
    tail -n 153 data/weka/iris.arff | head -n 150
  done | curl -H "Content-Type: text/plain" \
              -X POST --data-binary @- \
              http://localhost:8080/api/v1/models/iris_rf-1/stream
            

This completes end-to-end (including HTTP transfer and printing) in under 4 seconds for 150,000 samples.