Spring AI:让大模型住进 Spring 生态(三)

专栏:Spring AI 探索手札

个人主页:手握风云

目录

一、本地大模型部署

[1.1. 大模型部署方案对比](#1.1. 大模型部署方案对比)

[1.2. 本地部署核心:Ollama 工具](#1.2. 本地部署核心:Ollama 工具)

[1.3. Spring AI 接入 Ollama 本地模型](#1.3. Spring AI 接入 Ollama 本地模型)

[1. 创建项目](#1. 创建项目)

[2. 添加依赖](#2. 添加依赖)

[3. 配置文件](#3. 配置文件)

[4. 基础对话实现](#4. 基础对话实现)

[5. 流式响应实现](#5. 流式响应实现)

[6. ChatClient 封装](#6. ChatClient 封装)


一、本地大模型部署

1.1. 大模型部署方案对比

对比云服务部署和本地部署两种主流方案,核心差异:

  1. 费用:云部署前期成本低、长期计费高;本地部署前期硬件成本高、长期无额外费用。
  2. 维护:云部署简单省心;本地部署复杂,需自主维护。
  3. 弹性扩展:云部署易扩展;本地部署难度高、定制性强。
  4. 网络:云部署依赖公网;本地部署无网络依赖。
  5. 数据安全:云部署隐私性差;本地部署数据更安全。

1.2. 本地部署核心:Ollama 工具

本地部署首选 Ollama(开源工具,简化 LLM 安装、运行、管理,支持 DeepSeek、Qwen、LLaMA 等模型) 。

  • 下载 Ollama

Ollama 官网下载地址:https://ollama.com/download

  • 验证

访问 http://127.0.0.1:11434 或在 cmd 终端执行 ollama --version 校验。

  • 拉取模型

以 DeepSeek-R1 为例,按硬件配置选择参数量版本,如果电脑内存为 8 G,可以考虑 deepseek-r1:1.5b,其中"b" 代表十亿,表示该模型拥有15 亿个可训练参数,或者考虑其他的开源大模型。接着我们在命令行终端运行即可拉取。

bash 复制代码
ollama run deepseek-r1:1.5b
ollama run codegeex4

如果以前没有下载过,就会自动拉取,如果下载过,直接就可以进行对话了。

  • 命令行测试

1.3. Spring AI 接入 Ollama 本地模型

1. 创建项目

我们先在父工程 spring-ai-project 中新建子模块 spring-ollama-demo,完善基础 pom.xml(引入 Spring Boot Web、Test 依赖)与启动类。

XML 复制代码
<dependencies>
	<!-- Spring Web -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>

	<!-- 测试依赖 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<!-- 打包插件 -->
<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>
java 复制代码
package com.yang.ollama;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringOllamaApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringOllamaApplication.class, args);
    }
}

2. 添加依赖

导入 Spring AI BOM 做统一版本管理,引入 spring-ai-ollama-spring-boot-starter 核心启动器,实现 Ollama 与 Spring AI 的自动整合。

XML 复制代码
<!-- Spring AI 版本管理 -->
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.ai</groupId>
			<artifactId>spring-ai-bom</artifactId>
			<version>1.0.0-M6</version> <!-- Use the latest Milestone version -->
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>
XML 复制代码
<!-- Spring AI Ollama 核心启动器-->
<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>

3. 配置文件

在 application.yml 中配置服务端口、Ollama 本地服务地址(http://localhost:11434)、指定对话模型(如deepseek-r1:1.5b)。

java 复制代码
server:
  port: 8081

# Spring AI Ollama 配置
spring:
  application:
    name: spring-ollama-demo
  ai:
    ollama:
      # Ollama 本地服务地址
      base-url: http://localhost:11434
      chat:
        # 指定使用的大模型(提前通过 Ollama 拉取)
        model: deepseek-r1:1.5b
logging:
  pattern:
    console: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
    file: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
  level:
    org.springframework.ai.chat.client.advisor: debug

4. 基础对话实现

注入 OllamaChatModel,编写 /ollama/chat 接口,通过 call() 方法实现本地大模型的文本对话响应。

java 复制代码
package com.yang.ollama.controller;

import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/ollama")
public class OllamaController {
    @Autowired
    private OllamaChatModel chatModel;

    @RequestMapping("/chat")
    public String chat(String message) {
        return chatModel.call(message);
    }
}

访问接口:http://127.0.0.1:8081/ollama/chat?message=你是哪个模型?

5. 流式响应实现

基于 stream() 方法返回 Flux<String>,编写 /ollama/stream 接口,实现大模型逐字流式输出,提升交互体验。

java 复制代码
@RequestMapping(value = "/stream", produces = "text/html;charset=utf-8")
public Flux<String> stream(String message) {
    return chatModel.stream(message);
}

6. ChatClient 封装

通过配置类创建 ChatClientBean,绑定 Ollama 模型并设置默认系统角色;封装对话接口,实现带预设身份的智能对话。

java 复制代码
package com.yang.ollama.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatClientConfiguration {
    @Bean
    public ChatClient chatClient(OllamaChatModel chatModel) {
        return ChatClient.builder(chatModel)
                .defaultSystem("我是编码助手,擅长 Java 语法和集合框架")
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }
}
java 复制代码
package com.yang.ollama.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/chat")
public class ChatClientController {
    private final ChatClient chatClient;

    public ChatClientController(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    @RequestMapping("/call")
    public String call(String message) {
        return chatClient
                .prompt()
                .call()
                .content();
    }

    @RequestMapping(value = "/stream", produces = "text/html;charset=utf-8")
    public Flux<String> stream(String message) {
        return chatClient
                .prompt(message)
                .stream()
                .content();
    }
}

访问接口:llachttp://127.0.0.1:8081/chat/?message=你的职责是什么? http://127.0.0.1:8081/chat/stream?message=你的职责是什么?

相关推荐
萧瑟余晖几秒前
Spring Cloud Alibaba生态整合详解
spring·spring cloud·面试
涡能增压发动积1 分钟前
AI 对一位老开发的副作用总结
后端
估值探索者11 分钟前
【Python量化技术指标实战 04】布林带通道突破,怎么知道是真突破还是假突破?
java·开发语言·python·接口·股票数据api接口
未秃头的程序猿11 分钟前
同一个商户号,V2 免密代扣和 V3 分账的证书怎么共存?
java·后端·微信
captain37625 分钟前
Spring Boot的配置文件
java·spring boot·后端
captain37627 分钟前
Spring Boot日志
java·数据库·spring boot
Rabitebla1 小时前
【Linux】 权限篇(三):深入理解 umask 位运算与粘滞位的设计思想
java·linux·服务器·c++·笔记·学习
IT_陈寒1 小时前
为什么你应该学习React?
前端·人工智能·后端
每天一道题1 小时前
Kafka 为什么会重复消费?从 Producer ACK、Offset 到消息可靠性
后端·微服务
Pin_Qing1 小时前
缓存能活多久,现在是个要算的参数
java·大数据·开发语言·人工智能·程序人生