一、技术概述
Ollama 是轻量化本地大模型部署工具,支持一键部署 Qwen、Llama、LLaVA 等各类开源模型,无需复杂算力与编译配置,可实现本地私有化、零网络开销、数据不外泄的大模型推理能力。SpringAI 是 Spring 官方标准化 AI 开发框架,提供统一的模型调用抽象 API,可无缝适配云端模型与本地 Ollama 模型,实现业务代码无感切换。
本文基于 SpringBootTest 单元测试 实现全套实战能力,无需启动 Web 容器,专注模型调用调试,覆盖同步对话、流式输出、多模态图文识别三大核心场景,所有代码可直接运行、注释完整、适合学习与项目落地。
二、环境搭建与工程配置
2.1 Ollama 安装与模型拉取
本地部署 Ollama 并拉取对应模型,分别适配文本对话与图文多模态场景,终端执行以下命令:
-
安装 Ollama 客户端,默认本地服务地址:
http://localhost:11434 -
拉取通用文本对话模型:
ollama pull qwen3:7b -
拉取多模态图文识别模型:
ollama pull llava:7b
2.2 项目核心依赖(Maven)
项目基于 SpringBoot3,需引入 SpringAI Ollama 核心依赖、WebFlux 流式依赖、单元测试依赖,完整依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<dependencies>
<!-- SpringAI Ollama 核心适配依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
<version>1.0.0-M1</version>
</dependency>
<!-- 流式输出必备 WebFlux 响应式依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- SpringBoot 单元测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.3 全局配置文件(application.yml)
统一配置 Ollama 本地地址、默认模型、推理参数,所有测试类自动读取生效:
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: qwen3:7b
temperature: 0.3
num-ctx: 4096
三、测试工程通用规范
本文所有测试用例统一遵循以下规范,保证代码一致性与可复用性:
-
使用
@SpringBootTest注解加载 Spring 上下文,自动注入 Ollama 模型客户端; -
同步调用适用于离线批量处理,流式调用适用于实时分段输出场景;
-
多模态场景手动切换
llava:7b模型,覆盖图文识别能力; -
所有用例无需启动 Tomcat 容器,直接运行单元测试即可调试模型效果。
四、实战一:同步 Chat 对话单元测试
4.1 场景说明
同步调用为一次性阻塞请求,模型完整生成全部内容后统一返回结果,适合离线文本总结、批量问答、后台业务处理场景,代码简单、调试稳定。
4.2 完整可运行代码
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.api.OllamaChatOptions;
import org.springframework.boot.test.context.SpringBootTest;
/**
* Ollama 同步对话单元测试
* 适用场景:离线问答、文本总结、批量数据处理
*/
@SpringBootTest
public class OllamaSyncChatTest {
// 自动注入Ollama模型客户端,读取yml全局配置
@Resource
private ChatModel ollamaChatModel;
@Test
void testSyncChat() {
// 1. 定义用户提问内容
String question = "用简短语言解释SpringAI是什么";
//手动设置大模型
OllamaChatOptions ollamaChatOptions = OllamaChatOptions.builder()
.model("qwen2.5:7b")
.build();
// Prompt第二个参数:传入本次运行时option
Prompt prompt = new Prompt(question, ollamaChatOptions);
// 3. 同步调用本地大模型,阻塞等待完整返回
var chatResponse = ollamaChatModel.call(prompt);
// 4. 标准化提取AI回答内容
String answer = chatResponse.getResult().getOutput().getText();
// 控制台输出结果,方便调试查看
System.out.println("===== 同步问答完整回答 =====");
System.out.println(answer);
}
}
五、实战二:SSE 流式输出单元测试
5.1 场景说明
流式输出基于 WebFlux 响应式 Flux 实现,模型逐段返回文本分片,模拟前端打字机效果,解决长文本超时、响应卡顿问题,适配实时对话、交互式问答 场景。单元测试通过 blockLast() 阻塞主线程,等待全部数据流接收完毕。
5.2 完整可运行代码
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.boot.test.context.SpringBootTest;
import reactor.core.publisher.Flux;
import javax.annotation.Resource;
import java.util.Map;
import java.util.StringJoiner;
/**
* Ollama 流式对话单元测试
* 适用场景:实时对话、打字机效果、长文本流式输出
*/
@SpringBootTest
public class OllamaStreamChatTest {
@Resource
private ChatModel ollamaChatModel;
@Test
void testStreamChat() {
// 1. 定义用户提问内容
String question = "用简短语言解释SpringAI是什么";
//手动设置大模型
OllamaChatOptions ollamaChatOptions = OllamaChatOptions.builder()
.model("qwen2.5:7b")
.build();
// Prompt第二个参数:传入本次运行时option
Prompt prompt = new Prompt(question, ollamaChatOptions);
// 用于拼接所有流式分片,生成完整回答
StringJoiner fullContent = new StringJoiner("");
// 开启流式响应,逐段接收模型输出
Flux<String> streamFlux = ollamaChatModel.stream(prompt)
.map(resp -> resp.getResult().getOutput().getText())
.doOnNext(chunk -> {
// 实时打印每一段分片,模拟前端实时渲染
System.out.print(chunk);
fullContent.add(chunk);
});
// 阻塞主线程,等待所有流式数据推送完成
streamFlux.blockLast();
// 输出拼接后的完整回答
System.out.println("\n\n===== 流式拼接完整内容 =====");
System.out.println(fullContent);
}
}
六、实战三:多模态图文识别单元测试
6.1 场景说明
基于 llava:7b 多模态模型,支持图片+文本联合提问,实现图片内容识别、图像描述、看图问答等能力,可应用于图片解析、截图分析、图像内容审核等场景。
6.2 完整可运行代码
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.UrlResource;
import javax.annotation.Resource;
import java.net.MalformedURLException;
/**
* Ollama 多模态图文识别单元测试
* 依赖模型:llava:7b
* 功能:图片解析、图文问答、图像内容描述
*/
@SpringBootTest
public class OllamaMultiModalTest {
@Resource
private ChatModel ollamaChatModel;
@Test
void testImageChat() throws MalformedURLException {
// 1. 动态覆盖模型,指定多模态图文模型
ChatOptions multiModelOptions = ChatOptions.builder()
.model("llava:7b")
.temperature(0.2)
.build();
// 2. 替换为自己的有效可访问图片公网链接
// 1。本地磁盘绝对路径 D:/test/a.jpg 或者 /opt/image/a.jpg
String localFilePath = "C:/Users/65739/Downloads/ac1db2e4-80fb-4f92-bdc2-95a28b16dd75-1.png";
FileSystemResource imageResource = new FileSystemResource(localFilePath);
//2.资源文件下的图片路径
// ClassPathResource imageResource = new ClassPathResource("image/cat.jpg");
// 3. 替换为自己的有效可访问图片公网链接
// String imageUrl = "https://pic.baike.soso.com/ugc/baikepic2/21123/20220313152217_9856.jpg/0";
// UrlResource imageResource = new UrlResource(imageUrl);
//2.构建Media对象,封装图片资源 + MIME类型
Media media = Media.builder()
.mimeType(MimeTypeUtils.IMAGE_JPEG)
.data(imageResource)
.build();
//3.构建UserMessage,文本+图片媒体
String userQuestion = "详细描述这张图片里面有什么内容";
UserMessage userMsg = UserMessage.builder()
.text(userQuestion)
.media(media)
.build();
//4.组装Prompt,同时运行时指定多模态模型(llava)
Prompt prompt = new Prompt(List.of(userMsg), multiModelOptions);
var response = ollamaChatModel.call(prompt);
String result = response.getResult().getOutput().getText();
// 输出图片识别结果
System.out.println("===== 图片识别回答 =====");
System.out.println(result);
}
}
七、运行注意事项与避坑指南
-
服务前置校验 :运行测试前必须启动 Ollama 本地服务,确保
127.0.0.1:11434可正常访问。 -
模型匹配校验 :图文多模态场景必须指定
llava:7b,文本模型无法解析图片资源。 -
流式依赖必填:流式输出必须引入 WebFlux 依赖,否则 Flux 响应式类无法加载,测试报错。
-
硬件适配说明:7B 模型建议 4G 及以上独立显卡,无 N 卡将走 CPU 推理,速度大幅降低。
-
图片资源规范:多模态测试需使用有效可访问图片链接,无效/失效图片地址会导致解析失败。
八、方案优势总结
-
调试高效:基于单元测试运行,无需启动 Web 容器,节省项目启动耗时。
-
数据安全:全程本地模型推理,业务数据不上公网,满足私有化合规需求。
-
代码通用:遵循 SpringAI 统一 API,可无缝迁移为 Web 接口或云端模型调用。
-
场景全覆盖:同时支持文本问答、流式交互、图文多模态,满足绝大多数本地 AI 开发场景。