SpringBoot 集成 LangChain4j 本地调用 Ollama
本文介绍了如何在 SpringBoot 项目中集成 LangChain4j 框架以本地调用 Ollama 模型。内容包括 Ollama 软件及模型的下载方法,Maven 依赖配置,以及 SpringBoot 配置文件设置。通过示例代码展示了无记忆和有记忆的对话实现方式,并提供了项目启动运行的日志输出验证。适合希望将大语言模型能力接入 Java 应用的开发者参考。

本文介绍了如何在 SpringBoot 项目中集成 LangChain4j 框架以本地调用 Ollama 模型。内容包括 Ollama 软件及模型的下载方法,Maven 依赖配置,以及 SpringBoot 配置文件设置。通过示例代码展示了无记忆和有记忆的对话实现方式,并提供了项目启动运行的日志输出验证。适合希望将大语言模型能力接入 Java 应用的开发者参考。

LangChain4j 是一个专为 Java 生态系统设计的开源框架,旨在简化大语言模型(LLM)与应用程序的集成,提供了构建基于 LLM 的复杂应用所需的核心组件和工具。其设计理念借鉴了 Python 生态的 LangChain,但针对 Java 开发者的习惯和需求进行了优化。
| 维度 | LangChain4j | Spring AI |
|---|---|---|
| 定位 | 专注于 LLM 应用开发的工具链,类似 Java 版 LangChain | Spring 生态的官方 AI 扩展,提供标准化集成 |
| 生态依赖 | 独立框架,可与任何 Java 框架集成(包括 Spring) | 深度依赖 Spring 生态(如 Spring Boot、Spring Cloud) |
| 核心能力 | 提供完整的 LLM 应用组件(链、记忆、工具等) | 聚焦于模型接口标准化、数据处理、集成能力 |
| 模型支持 | 支持主流闭源/开源模型,配置灵活 | 支持主流模型,通过统一接口抽象,符合 Spring 风格 |
| 易用性 | 需手动组合组件,灵活性高,但学习成本略高 | 遵循 Spring 约定优于配置,开箱即用,适合 Spring 开发者 |
| 企业级特性 | 需自行集成安全、监控等特性 | 天然支持 Spring 生态的企业级特性(如安全、审计、监控) |
| 社区与更新 | 社区活跃,更新频率中等 | 官方背书,更新频繁,与 Spring 版本同步演进 |
| 适用场景 | 复杂 LLM 应用(如多链协作、自定义记忆策略) | 快速集成 LLM 到 Spring 应用,追求标准化和稳定性 |
复制内容到 ollama_download.ps1 文件中
# 定义模型名称避免硬编码
$modelName = "gemma3:27b"
# 设置重试参数
$maxRetries = 50
$retryInterval = 3 # 秒
$downloadTimeout = 80 # 秒
for($retry = 1;$retry-le-$maxRetries;$retry++){
# 精确检查模型是否存在
$modelExists = ollama list |Where-Object{$_-match"\b$modelName\b"}
if($modelExists){
Write-Host"[$(Get-Date)] model is already downloaded!"
exit 0
}
Write-Host"[$(Get-Date)] start $retry times downloading..."
# 启动进程并显示实时输出
$process = Start-Process -FilePath "ollama" `
-ArgumentList "run",$modelName `
-PassThru `
-NoNewWindow
# 等待下载完成或超时
try{
$process|Wait-Process -Timeout $downloadTimeout -ErrorAction Stop
}catch{
# 超时处理
Write-Host"download timeout, safe terminate process..."
$process|Stop-Process -Force
}
if(-not$process.HasExited){
$process|Stop-Process -Force
Write-Host"process terminated due to timeout."
}else{
# 检查退出代码
if($process.ExitCode -eq 0){
Write-Host"download success!"
exit 0
}
Write-Host"download failed, exit code: $($process.ExitCode)"
}
Start-Sleep -Seconds $retryInterval
}
Write-Host"exceeded maximum retries ($maxRetries), download failed."
exit 1
PS C:\Users\xuhya\Desktop> ollama list
NAME ID SIZE MODIFIED
gemma3:27b a418f5838eaf 17 GB 2 minutes ago
gemma3:latest a2af6cc3eb7f 3.3 GB 7 minutes ago
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.6</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>lang-chain-ollama</artifactId>
<version>1.0.0</version>
<name>lang-chain-ollama</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>25</java.version>
</properties>
<dependencies>
<!--Spring Boot 的 Web starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--LangChain4j 针对 OpenAI 的 Spring Boot starter-->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
</dependency>
<!--Spring Boot 的开发工具,提供热部署、自动重启等功能,加速开发过程-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--简化 Java 代码的工具库-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--Spring Boot 的测试 starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>1.6.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
server:
port: 8080
spring:
application:
name: lang-chain-ollama
logging:
file:
name: logs/lang-chain-ollama.log
level:
root: INFO
com.example: INFO
langchain4j:
ollama:
chat-model:
base-url: http://127.0.0.1:11434
model-name: llama3.2-vision:latest
temperature: 0.7
timeout: 600s
package com.example.chat.controller;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.ollama.OllamaChatModel;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@AllArgsConstructor
@RequestMapping("/ollama")
public class OllamaController {
private final OllamaChatModel ollama;
@GetMapping("/model/chat")
public Object chat(@RequestParam(value = "message", defaultValue = "你好") String message) {
ChatRequest request = ChatRequest.builder()
.messages(UserMessage.userMessage(TextContent.from(message)))
.build();
ChatResponse chat = ollama.chat(request);
return chat.aiMessage().text();
}
}
package com.example.chat.controller;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.ollama.OllamaChatModel;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@AllArgsConstructor
@RequestMapping("/ollama/memory")
public class MemoryController {
private final OllamaChatModel ollama;
private final ChatMemory chatMemory;
@GetMapping("/model/chat")
public Object chat(@RequestParam(value = "message", defaultValue = "你好") String message) {
// 将用户消息添加到聊天历史
UserMessage userMessage = UserMessage.userMessage(TextContent.from(message));
chatMemory.add(userMessage);
// 构建包含历史记录的请求
ChatRequest request = ChatRequest.builder().messages(chatMemory.messages()).build();
// 获取模型响应
ChatResponse response = ollama.chat(request);
var aiMessage = response.aiMessage();
// 将 AI 响应也加入聊天历史
chatMemory.add(aiMessage);
return aiMessage;
}
}
. ____ _ __ _ _ /\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( )\___ | '_ |'_| | '_ \/ _` | \ \ \ \/ ___)||_)|||||||(_||)))) ' |____|.__|_||_|_||_,|////=========|_|==============|___/=/_/_/_/
::SpringBoot::(v3.5.6)
2025-10-09T21:59:48.238+08:00 INFO 20840---[lang-chain][ restartedMain]com.example.LangChainApplication:Starting LangChainApplication using Java25 with PID 20840 (<project-path>) started by <username> in <project-path>
2025-10-09T21:59:48.241+08:00 INFO 20840---[lang-chain][ restartedMain]com.example.LangChainApplication:No active profile set, falling back to 1 default profile:"default"
2025-10-09T21:59:48.317+08:00 INFO 20840---[lang-chain][ restartedMain].e.DevToolsPropertyDefaultsPostProcessor :Devtools property defaults active!Set'spring.devtools.add-properties'to'false'todisable
2025-10-09T21:59:48.317+08:00 INFO 20840---[lang-chain][ restartedMain].e.DevToolsPropertyDefaultsPostProcessor :For additional web related logging consider setting the 'logging.level.web' property to'DEBUG'
2025-10-09T21:59:49.575+08:00 INFO 20840---[lang-chain][ restartedMain]o.s.b.w.embedded.tomcat.TomcatWebServer:Tomcat initialized with port 8080(http)
2025-10-09T21:59:49.595+08:00 INFO 20840---[lang-chain][ restartedMain]o.apache.catalina.core.StandardService:Starting service [Tomcat]
2025-10-09T21:59:49.601+08:00 INFO 20840---[lang-chain][ restartedMain]o.apache.catalina.core.StandardEngine:Starting Servlet engine:[Apache Tomcat/10.1.46]
2025-10-09T21:59:49.649+08:00 INFO 20840---[lang-chain][ restartedMain]o.a.c.c.C.[Tomcat].[localhost].[/]:Initializing Spring embedded WebApplicationContext
2025-10-09T21:59:49.649+08:00 INFO 20840---[lang-chain][ restartedMain]w.s.c.ServletWebServerApplicationContext:RootWebApplicationContext: initialization completed in 1331 ms
2025-10-09T21:59:50.163+08:00 INFO 20840---[lang-chain][ restartedMain]o.s.b.d.a.OptionalLiveReloadServer:LiveReload server is running on port 35729
2025-10-09T21:59:50.208+08:00 INFO 20840---[lang-chain][ restartedMain]o.s.b.w.embedded.tomcat.TomcatWebServer:Tomcat started on port 8080(http)with context path '/'
2025-10-09T21:59:50.221+08:00 INFO 20840---[lang-chain][ restartedMain]com.example.LangChainApplication:Started LangChainApplication in 2.791 seconds (process running for 3.655)

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
暂无推荐文章,稍后可再来查看。
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online