SpringBoot 集成 LangChain4j 本地调用 Ollama

SpringBoot 集成 LangChain4j 本地调用 Ollama

  • [1 Ollama 软件下载](#1 Ollama 软件下载)
  • [2 Ollama 模型下载](#2 Ollama 模型下载)
    • [2.1 PowerShell 下载脚本](#2.1 PowerShell 下载脚本)
    • [2.2 Ollama模型运行](#2.2 Ollama模型运行)
  • [3 SpringBoot 集成 LangChain4j](#3 SpringBoot 集成 LangChain4j)
    • [3.1 pom依赖](#3.1 pom依赖)
    • [3.2 yml配置](#3.2 yml配置)
    • [3.3 bean配置](#3.3 bean配置)
    • [3.4 无记忆](#3.4 无记忆)
    • [3.5 有记忆](#3.5 有记忆)
  • [5 SpringBoot 运行测试](#5 SpringBoot 运行测试)

1 Ollama 软件下载

Ollama

2 Ollama 模型下载

2.1 PowerShell 下载脚本

复制内容到ollama_download.ps1文件中

powershell 复制代码
# 定义模型名称避免硬编码
$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
powershell 复制代码
PS C:\Users\xuhya\Desktop> .\ollama_download.ps1
[10/09/2025 21:42:20] start 1 times downloading...
pulling manifest
pulling e796792eba26:  98% ▕████████████████████████████████████████████████████████  ▏  17 GB/ 17 GB  1.7 MB/s   3m20sdownload timeout, safe terminate process...
download failed, exit code: -1
[10/09/2025 21:43:43] start 2 times downloading...
pulling manifest
pulling e796792eba26: 100% ▕██████████████████████████████████████████████████████████▏  17 GB
pulling e0a42594d802: 100% ▕██████████████████████████████████████████████████████████▏  358 B
pulling dd084c7d92a3: 100% ▕██████████████████████████████████████████████████████████▏ 8.4 KB
pulling 3116c5225075: 100% ▕██████████████████████████████████████████████████████████▏   77 B
pulling f838f048d368: 100% ▕██████████████████████████████████████████████████████████▏  490 B
verifying sha256 digest ⠸ download timeout, safe terminate process...
download failed, exit code: -1
[10/09/2025 21:45:06] start 3 times downloading...
pulling manifest
pulling e796792eba26: 100% ▕██████████████████████████████████████████████████████████▏  17 GB
pulling e0a42594d802: 100% ▕██████████████████████████████████████████████████████████▏  358 B
pulling dd084c7d92a3: 100% ▕██████████████████████████████████████████████████████████▏ 8.4 KB
pulling 3116c5225075: 100% ▕██████████████████████████████████████████████████████████▏   77 B
pulling f838f048d368: 100% ▕██████████████████████████████████████████████████████████▏  490 B
verifying sha256 digest
writing manifest
success
⠏ download timeout, safe terminate process...
download failed, exit code: -1
[10/09/2025 21:46:29] model is already downloaded!
PS C:\Users\xuhya\Desktop>

2.2 Ollama模型运行

powershell 复制代码
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
PS C:\Users\xuhya\Desktop>

3 SpringBoot 集成 LangChain4j

3.1 pom依赖

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         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/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.xu</groupId>
    <artifactId>lang-chain</artifactId>
    <version>1.0.0</version>
    <name>lang-chain</name>

    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>25</java.version>
    </properties>

    <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>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-ollama</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <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>

3.2 yml配置

yml 复制代码
server:
  port: 8080

spring:
  application:
    name: lang-chain

logging:
  file:
    name: logs/spring-oracle.log
  level:
    root: INFO
    com.xu: INFO

langchain4j:
  ollama:
    chat-model:
      base-url: http://127.0.0.1:11434
      model-name: gemma3:latest

3.3 bean配置

java 复制代码
package com.xu.conf;

import dev.langchain4j.http.client.spring.restclient.SpringRestClientBuilder;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.model.ollama.OllamaStreamingChatModel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

@Configuration
public class OllamaConfig {

	@Value("${langchain4j.ollama.chat-model.model-name}")
	private String modelName;

	@Value("${langchain4j.ollama.chat-model.base-url}")
	private String baseUrl;

	@Bean
	public OllamaChatModel ollamaChatModel() {
		return OllamaChatModel.builder()
				.modelName(modelName)
				.baseUrl(baseUrl)
				.httpClientBuilder(new SpringRestClientBuilder())
				.timeout(Duration.ofHours(10)) // 超时时间
				.maxRetries(3) // 超时最大重试次数
				.build();
	}

	@Bean
	public ChatMemory chatMemory() {
		return MessageWindowChatMemory.withMaxMessages(10); // 最多保存10条消息
	}

	@Bean
	public OllamaStreamingChatModel ollamaStreamingChatModel() {
		return OllamaStreamingChatModel.builder()
				.modelName(modelName)
				.baseUrl(baseUrl)
				.httpClientBuilder(new SpringRestClientBuilder())
				.timeout(Duration.ofHours(10)) // 超时时间
				// 其他参数(可选):温度值(0.0-1.0,越低越确定)
				.temperature(0.7)
				.build();
	}

}

3.4 无记忆

java 复制代码
package com.xu.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();
	}

}

3.5 有记忆

java 复制代码
package com.xu.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;
	}


}

5 SpringBoot 运行测试

java 复制代码
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.5.6)

2025-10-09T21:59:48.238+08:00  INFO 20840 --- [lang-chain] [  restartedMain] com.xu.LangChainApplication              : Starting LangChainApplication using Java 25 with PID 20840 (D:\SourceCode\Learn\lang-chain\target\classes started by xuhya in D:\SourceCode\Learn\lang-chain)
2025-10-09T21:59:48.241+08:00  INFO 20840 --- [lang-chain] [  restartedMain] com.xu.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' to disable
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 : Root WebApplicationContext: 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.xu.LangChainApplication              : Started LangChainApplication in 2.791 seconds (process running for 3.655)
相关推荐
兔兔爱学习兔兔爱学习5 小时前
Spring Al学习7:ImageModel
java·学习·spring
lang201509286 小时前
Spring远程调用与Web服务全解析
java·前端·spring
m0_564264187 小时前
IDEA DEBUG调试时如何获取 MyBatis-Plus 动态拼接的 SQL?
java·数据库·spring boot·sql·mybatis·debug·mybatis-plus
崎岖Qiu7 小时前
【设计模式笔记06】:单一职责原则
java·笔记·设计模式·单一职责原则
Hello.Reader7 小时前
Flink ExecutionConfig 实战并行度、序列化、对象重用与全局参数
java·大数据·flink
熊小猿8 小时前
在 Spring Boot 项目中使用分页插件的两种常见方式
java·spring boot·后端
paopaokaka_luck8 小时前
基于SpringBoot+Vue的助农扶贫平台(AI问答、WebSocket实时聊天、快递物流API、协同过滤算法、Echarts图形化分析、分享链接到微博)
java·vue.js·spring boot·后端·websocket·spring
老华带你飞8 小时前
机器人信息|基于Springboot的机器人门户展示系统设计与实现(源码+数据库+文档)
java·数据库·spring boot·机器人·论文·毕设·机器人门户展示系统
notion20258 小时前
Adobe Lightroom Classic下载与安装教程(附安装包) 2025最新版详细图文安装教程
java·数据库·其他·adobe
rengang669 小时前
351-Spring AI Alibaba Dashscope 多模型示例
java·人工智能·spring·多模态·spring ai·ai应用编程