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)
相关推荐
ywf121512 小时前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
大阿明19 小时前
Spring Boot(快速上手)
java·spring boot·后端
哆啦A梦158819 小时前
Springboot整合MyBatis实现数据库操作
数据库·spring boot·mybatis
bearpping19 小时前
Java进阶,时间与日期,包装类,正则表达式
java
邵奈一19 小时前
清明纪念·时光信笺——项目运行指南
java·实战·项目
sunwenjian88620 小时前
Java进阶——IO 流
java·开发语言·python
sinat_2554878120 小时前
读者、作家 Java集合学习笔记
java·笔记·学习
皮皮林55120 小时前
如何画出一张优秀的架构图?(老鸟必备)
java
百锦再20 小时前
Java 并发编程进阶,从线程池、锁、AQS 到并发容器与性能调优全解析
java·开发语言·jvm·spring·kafka·tomcat·maven
森林猿20 小时前
java-modbus-读取-modbus4j
java·网络·python