主题
jitLLM
jitLLM 在 JVM 内运行 GGUF 格式的 LLM。 它通过 TornadoVM 在 GPU 上运行, 后者会为 CUDA、OpenCL 或 Metal 即时编译(JIT)模型的算子内核,也可在 CPU 上运行。 无需单独的推理服务器。
项目搭建
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-jitllm</artifactId>
<version>1.22.0-beta32</version>
</dependency>groovy
implementation 'dev.langchain4j:langchain4j-jitllm:1.22.0-beta32'要求
- JDK 21 或更新版本。在 JDK 21 上,参见在 JDK 21 上运行。
- GGUF 格式的模型(FP16、Q8_0 或 Q4_0)。支持的模型系列包括 Llama 3、Mistral、Qwen 2.5、Qwen 3、 Phi-3、IBM Granite 3.3 / 4.0、Gemma 4 与 DeepSeek-R1-Distill。 已测试的模型汇集在 Hugging Face 上。
- JVM 选项
--add-modules jdk.incubator.vector。 - 要在 GPU 上运行:针对你的 JDK 系列(
jdk21或jdk22plus) 以及 GPU 后端的 TornadoVM SDK, 例如用 SDKMAN! 安装(sdk install tornadovm)。 JVM 必须通过 TornadoVM 的tornado启动器并带-Duse.tornadovm=true启动。 - 要在纯 JVM(不经 TornadoVM 启动器)的 CPU 上运行:以
runtime依赖引入io.github.beehive-lab:tornado-api:7.0.1-jdk22plus(JDK 21 上用7.0.1-jdk21)。通过 TornadoVM 运行时无需引入,它已自带。
仅支持 JVM 模式;不支持 GraalVM 本地镜像。
在 JDK 21 上运行
jitLLM 发布两种构建:jdk22plus(langchain4j-jitllm 所依赖的)与 jdk21。 在 JDK 21 上,把前者换成后者,并让 JVM 以 --enable-preview 启动, 因为 jdk21 构建使用外部函数与内存 API,这在 JDK 21 中是预览特性:
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-jitllm</artifactId>
<version>1.22.0-beta32</version>
<exclusions>
<exclusion>
<groupId>io.github.beehive-lab</groupId>
<artifactId>jitllm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.github.beehive-lab</groupId>
<artifactId>jitllm</artifactId>
<version>1.0.2-jdk21</version>
</dependency>聊天
java
try (JitLLMChatModel model = JitLLMChatModel.builder()
.modelPath(Path.of("Qwen3-0.6B-Q8_0.gguf"))
.build()) {
String answer = model.chat("What is the capital of Germany?");
}模型在构建时被加载,并一直保有其内存(包括 GPU 内存),直到调用 close()。 请只构建一次并复用。
流式传输
java
try (JitLLMStreamingChatModel model = JitLLMStreamingChatModel.builder()
.modelPath(Path.of("Qwen3-0.6B-Q8_0.gguf"))
.build()) {
model.chat("Tell me a story", new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
System.out.print(partialResponse);
}
@Override
public void onCompleteResponse(ChatResponse completeResponse) {
System.out.println();
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
});
}chat(...) 会在响应完成后返回:模型在调用线程中运行,处理器也在该线程上被调用。 若要避免阻塞,请从另一个线程(例如虚拟线程)调用它。 流式可通过 onPartialResponse(PartialResponse, PartialResponseContext) 中可用的 StreamingHandle 来停止。
在 GPU 上运行
bash
tornado --jvm="-Duse.tornadovm=true --add-modules jdk.incubator.vector -Dtornado.device.memory=8GB" \
-cp "target/my-app.jar:target/dependency/*" com.example.Maintarget/dependency 可用 mvn dependency:copy-dependencies 填充。 以这种方式启动 JVM 时,模型会在 GPU 上运行,使用 TornadoVM SDK 提供的后端。 onGPU(false) 强制使用 CPU,而 onGPU(true) 在 JVM 未经 TornadoVM 启动时会在构建期失败。
配置
| Builder 方法 | 默认值 | 描述 |
|---|---|---|
modelPath | 必填 | GGUF 文件的路径。 |
contextLength | 4096 | 整个对话(含响应)的最大词元数。其内存在加载时预留。 |
onGPU | 以 -Duse.tornadovm=true 启动时为 true | 在 GPU 还是在 CPU 上运行。 |
temperature | 0.1 | 采样温度。 |
topP | 0.95 | 核采样概率。 |
maxTokens | 512 | 每次响应生成的最大词元数,含思考部分。 |
stopSequences | 结束响应的序列。它们作用于答案,而非思考。 | |
seed | 每次请求随机 | 采样的种子,用于可复现的响应。 |
think | 模型默认 | 推理模型是否先思考再回答。false 使其直接回答。 |
returnThinking | false | 在 AiMessage.thinking() 中返回推理模型的思考,并通过 onPartialThinking 流式输出。 |
defaultRequestParameters | 默认的 ChatRequestParameters;上述值优先。 | |
listeners | 关于请求、响应与错误通知的监听器。 |
temperature、topP、maxOutputTokens 和 stopSequences 也可在 ChatRequestParameters 中逐次请求设置。
一个模型实例可由多个线程使用,但它一次只生成一个响应: 并发请求会相互等待。
能力
- 流式,带取消。
- 工具,同步与流式,包括一次响应中的多个工具调用。 使用工具时,流式响应会在完成时一次性交付。
- 推理模型的思考(
<think>与</think>之间的文本):可用think开关, 并在设置了returnThinking(true)时返回。 ChatResponse中的词元用量与结束原因。- 不支持:JSON 响应格式、
ToolChoice.REQUIRED、图像,以及modelName、topK、frequencyPenalty与presencePenalty参数。
从 GPULlama3.java 迁移
jitLLM 是 GPULlama3.java 的后继者,langchain4j-jitllm 取代了已弃用的 langchain4j-gpu-llama3 模块:
- 将
GPULlama3ChatModel替换为JitLLMChatModel,将GPULlama3StreamingChatModel替换为JitLLMStreamingChatModel。 maxTokens现在只限制生成的词元数。上下文窗口由contextLength设置。- 用
close()释放内存,而非freeTornadoVMGPUResources()。模型被垃圾回收时 不再有自动清理。 - 思考只有在设置了
returnThinking(true)时才返回,且不带<think>标签。 printLastMetrics()由ChatResponse.tokenUsage()取代。- 当未设置
onGPU时,仅当 JVM 以-Duse.tornadovm=true启动时,模型才在 GPU 上运行。