需要 Java 20 及以上,且用到 Java 21 预览特性,需加 --enable-preview 和 jdk.incubator.vector 模块;模型不会自动就位,CLI 要加 --auto-download 或先用 download 命令拉取;restapi 默认监听 8080 端口,可能与其他服务冲突。

curl -Ls https://sh.jbang.dev | bash -s - app setup
jbang app install --force jlama@tjake
jlama restapi tjake/Llama-3.2-1B-Instruct-JQ4 --auto-downloadREADME 未说明具体显存或 GPU 型号要求,仅提到后端可选 Panama Vector(默认)、Native SIMD 和实验性 WebGPU。
纯 Java 的 LLM 推理引擎,让你直接在 Java 应用里跑大模型
用纯 Java 实现的现代 LLM 推理引擎,支持 LLaMA、GPT 等 Transformer 模型,借助 SIMD 加速在 JVM 上直接跑大模型推理。
核心能力
- 实现 Paged Attention 管理 KV 缓存
- 支持 Mixtral 等 Mixture of Experts 模型
- 内置 Tool Calling 与 Embedding 生成
- 读取 HuggingFace SafeTensors 模型与分词器
- 支持 Q8/Q4 量化与分布式推理
容易踩的坑
- v0.8.4最新正式版2025-01-01 · 2025-01-01 19:28 UTC
What's Changed
- Feat add clean generate method by @DumiJDev in https://github.com/tjake/Jlama/pull/125
- Fix issue #134 by @c2an1 in https://github.com/tjake/Jlama/pull/135
- Let Auth Token be defined as env or sys prop by @lordofthejars in https://github.com/tjake/Jlama/pull/120
- Fix prompt usage when sharing the same session id (by stripping out t… by @tjake in https://github.com/tjake/Jlama/pull/136
- Fix coordinator port setting by @tjake in https://github.com/tjake/Jlama/pull/137
- Handle large prompts by splitting them into smaller batches so they d… by @tjake in https://github.com/tjake/Jlama/pull/139
- Feat add generate builder by @DumiJDev in https://github.com/tjake/Jlama/pull/127
New Contributors
- @c2an1 made their first contribution in https://github.com/tjake/Jlama/pull/135
Full Changelog: https://github.com/tjake/Jlama/compare/v0.8.3...v0.8.4
- v0.8.32024-11-24 · 2024-11-24 21:27 UTC
查看更新说明
What's Changed
- fix: Downloader method name, rename from notDownloadWieghts to notDow… by @DumiJDev in https://github.com/tjake/Jlama/pull/114
- Fix json parsing of >1 tool calls by @tjake in https://github.com/tjake/Jlama/pull/124
New Contributors
- @DumiJDev made their first contribution in https://github.com/tjake/Jlama/pull/114
Full Changelog: https://github.com/tjake/Jlama/compare/v0.8.2...v0.8.3
- v0.8.22024-11-05 · 2024-11-05 04:37 UTC
查看更新说明
What's Changed
- Better json detection and extraction from strings by @tjake in https://github.com/tjake/Jlama/pull/105
Full Changelog: https://github.com/tjake/Jlama/compare/v0.8.1...v0.8.2
- v0.8.12024-11-04 · 2024-11-04 04:05 UTC
查看更新说明
What's Changed
- Add missing F32 Q4 operations for arm by @tjake in https://github.com/tjake/Jlama/pull/103
Full Changelog: https://github.com/tjake/Jlama/compare/v0.8.0...v0.8.1
- v0.8.02024-10-30 · 2024-10-30 00:45 UTC
查看更新说明
What's Changed
- Adds Downloader class to add fluent coding when different options by @lordofthejars in https://github.com/tjake/Jlama/pull/87
- chore: update JlamaRingWorkerService.java by @eltociear in https://github.com/tjake/Jlama/pull/90
- Gemma2 classifier sample by @tjake in https://github.com/tjake/Jlama/pull/92
- Add utf-8 charset to ui by @LuccaPrado in https://github.com/tjake/Jlama/pull/96
- Fix qwen tokenizer since they use more than one by @tjake in https://github.com/tjake/Jlama/pull/99
- Add support for granite models by @mariofusco in https://github.com/tjake/Jlama/pull/98
- Keep kv-cache to the actual data stays on disk but mmap is removed af… by @tjake in https://github.com/tjake/Jlama/pull/100
New Contributors
- @eltociear made their first contribution in https://github.com/tjake/Jlama/pull/90
- @LuccaPrado made their first contribution in https://github.com/tjake/Jlama/pull/96
- @mariofusco made their first contribution in https://github.com/tjake/Jlama/pull/98
Full Changelog: https://github.com/tjake/Jlama/compare/v0.7.0...v0.8.0
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
🦙 Jlama: A modern LLM inference engine for Java
🚀 Features
Model Support:
- Gemma & Gemma 2 Models
- Llama & Llama2 & Llama3 Models
- Mistral & Mixtral Models
- Qwen2 Models
- IBM Granite Models
- GPT-2 Models
- BERT Models
- BPE Tokenizers
- WordPiece Tokenizers
Implements:
- Paged Attention
- Mixture of Experts
- Tool Calling
- Generate Embeddings
- Classifier Support
- Huggingface SafeTensors model and tokenizer format
- Support for F32, F16, BF16 types
- Support for Q8, Q4 model quantization
- Fast GEMM operations
- Distributed Inference!
Jlama requires Java 20 or later and it built with the following backends:
- Panama Vector (default)
- Native SIMD (optional)
- WebGPU (optional, experimental)
🤔 What is it used for?
Add LLM Inference directly to your Java application. To learn more read the DeepWiki docs.
🔬 Quick Start
🕵️♀️ How to use as a local client (with jbang!)
Jlama includes a command line tool that makes it easy to use.
The CLI can be run with jbang.
#Install jbang (or https://www.jbang.dev/download/)
curl -Ls https://sh.jbang.dev | bash -s - app setup
#Install Jlama CLI (will ask if you trust the source)
jbang app install --force jlama@tjake
Now that you have jlama installed you can download a model from huggingface and chat with it. Note I have pre-quantized models available at https://hf.co/tjake
# Run the openai chat api and UI on a model
jlama restapi tjake/Llama-3.2-1B-Instruct-JQ4 --auto-download
open browser to http://localhost:8080/
Usage:
jlama [COMMAND]
Description:
Jlama is a modern LLM inference engine for Java!
Quantized models are maintained at https://hf.co/tjake
Choose from the available commands:
Inference:
chat Interact with the specified model
restapi Starts a openai compatible rest api for interacting with this model
complete Completes a prompt using the specified model
Distributed Inference:
cluster-coordinator Starts a distributed rest api for a model using cluster workers
cluster-worker Connects to a cluster coordinator to perform distributed inference
Other:
download Downloads a HuggingFace model - use owner/name format
list Lists local models
quantize Quantize the specified model
rm Removes local model
version Display JLama version information
👨💻 How to use in your Java project
The main purpose of Jlama is to provide a simple way to use large language models in Java.
The simplest way to embed Jlama in your app is with the Langchain4j Integration.
If you would like to embed Jlama without langchain4j, add the following maven dependencies to your project:
<dependency>
<groupId>com.github.tjake</groupId>
<artifactId>jlama-core</artifactId>
<version>${jlama.version}</version>
</dependency>
<dependency>
<groupId>com.github.tjake</groupId>
<artifactId>jlama-native</artifactId>
<!-- supports linux-x86_64, macos-x86_64/aarch_64, windows-x86_64
Use https://github.com/trustin/os-maven-plugin to detect os and arch -->
<classifier>${os.detected.name}-${os.detected.arch}</classifier>
<version>${jlama.version}</version>
</dependency>
jlama uses Java 21 preview features. You can enable the features globally with:
export JDK_JAVA_OPTIONS="--add-modules jdk.incubator.vector --enable-preview"
or enable the preview features by configuring maven compiler and failsafe plugins.
Then you can use the Model classes to run models:
public void sample() throws IOException {
String model = "tjake/Llama-3.2-1B-Instruct-JQ4";
String workingDirectory = "./models";
String prompt = "What is the best season to plant avocados?";
// Downloads the model or just returns the local path if it's already downloaded
File localModelPath = new Downloader(workingDirectory, model).huggingFaceModel();
// Loads the quantized model and specified use of quantized memory
AbstractModel m = ModelSupport.loadModel(localModelPath, DType.F32, DType.I8);
PromptContext ctx;
// Checks if the model supports chat prompting and adds prompt in the expected format for this model
if (m.promptSupport().isPresent()) {
ctx = m.promptSupport()
.get()
.builder()
.addSystemMessage("You are a helpful chatbot who writes short responses.")
.addUserMessage(prompt)
.build();
} else {
ctx = PromptContext.of(prompt);
}
System.out.println("Prompt: " + ctx.getPrompt() + "\n");
// Generates a response to the prompt and prints it
// The api allows for streaming or non-streaming responses
// The response is generated with a temperature of 0.7 and a max token length of 256
Generator.Response r = m.generate(UUID.randomUUID(), ctx, 0.0f, 256, (s, f) -> {});
System.out.println(r.responseText);
}
Or you can use a Builder API:
public void sample() throws IOException {
String model = "tjake/Llama-3.2-1B-Instruct-JQ4";
String workingDirectory = "./models";
String prompt = "What is the best season to plant avocados?";
// Downloads the model or just returns the local path if it's already downloaded
File localModelPath = new Downloader(workingDirectory, model).huggingFaceModel();
// Loads the quantized model and specified use of quantized memory
AbstractModel m = ModelSupport.loadModel(localModelPath, DType.F32, DType.I8);
PromptContext ctx;
// Checks if the model supports chat prompting and adds prompt in the expected format for this model
if (m.promptSupport().isPresent()) {
ctx = m.promptSupport()
.get()
.builder()
.addSystemMessage("You are a helpful chatbot who writes short responses.")
.addUserMessage(prompt)
.build();
} else {
ctx = PromptContext.of(prompt);
}
System.out.println("Prompt: " + ctx.getPrompt() + "\n");
// Generates a response to the prompt and prints it
// The api allows for streaming or non-streaming responses
// The response is generated with a temperature of 0.7 and a max token length of 256
Generator.Response r = m.generateBuilder()
.session(UUID.randomUUID()) //By default, UUID.randomUUID()
.promptContext(ctx) // Required or use prompt(String text)
.ntokens(256) //By default, 256
.temperature(0.0f) //By default, 0.0f
.onTokenWithTimings((s, aFloat) -> {}) //By default, (s, aFloat) -> {}, nothing
.generate();
System.out.println(r.responseText);
}
You can simplify promptSupport using:
public void sample() throws IOException {
String model = "tjake/Llama-3.2-1B-Instruct-JQ4";
String workingDirectory = "./models";
String prompt = "What is the best season to plant avocados?";
// Downloads the model or just returns the local path if it's already downloaded
File localModelPath = new Downloader(workingDirectory, model).huggingFaceModel();
// Loads the quantized model and specified use of quantized memory
AbstractModel m = ModelSupport.loadModel(localModelPath, DType.F32, DType.I8);
var systemPrompt = "You are a helpful chatbot who writes short responses.";
PromptContext ctx = m.prompt()
.addUserMessage(prompt)
.addSystemMessage(systemPrompt)
.build(); //build method will create a PromptContext, if model don't support prompt, a simple PromptContext object will be created
System.out.println("Prompt: " + ctx.getPrompt() + "\n");
// Generates a response to the prompt and prints it
// The api allows for streaming or non-streaming responses
// The response is generated with a temperature of 0.7 and a max token length of 256
Generator.Response r = m.generateBuilder()
.session(UUID.randomUUID()) //By default, UUID.randomUUID()
.promptContext(ctx) // Required or use prompt(String text)
.ntokens(256) //By default, 256
.temperature(0.0f) //By default, 0.0f
.onTokenWithTimings((s, aFloat) -> {}) //By default, (s, aFloat) -> {}, nothing
.generate();
System.out.println(r.responseText);
}
Devloping Jlama
See DEVELOPER_GUIDE.md for more information.
⭐ Give us a Star!
If you like or are using this project to build your own, please give us a star. It's a free way to show your support.
🗺️ Roadmap
- Support more and more models
- Add pure java tokenizers
- Support Quantization (e.g. k-quantization)
- Add LoRA support
- GraalVM support
- Add distributed inference
🏷️ License and Citation
The code is available under Apache License.
If you find this project helpful in your research, please cite this work at
@misc{jlama2024,
title = {Jlama: A modern Java inference engine for large language models},
url = {https://github.com/tjake/jlama},
author = {T Jake Luciani},
month = {January},
year = {2024}
}