第二章 Ollama 本地大模型调用
s01 > [ s02 ] > s03 > s04 > s05 > s06 > s07 > s08 > s09 > s10 > s11 > s12 > s13 > s14 > s15 > s16 > s17 > s18
"模型跑在本地, 控制权就在自己手里" -- Ollama 解决的是联网依赖、隐私顾虑和实验自由度。
一、为什么要用本地大模型?
1.1 远程调用的问题
在上一章中,我们使用的是阿里云百炼平台的远程 AI 服务。这意味着:
- 每次调用都需要联网
- 所有的数据都要经过第三方服务器(隐私问题)
- 有 API 调用配额和费用
- 网络延迟影响响应速度
1.2 本地部署的优势
Ollama 是一个让你可以在自己电脑上运行大模型的神器:
| 对比项 | 阿里云远程调用 | Ollama 本地调用 |
|---|---|---|
| 网络要求 | 必须联网 | 不需要(局域网即可) |
| 隐私安全 | 数据上传云端 | 完全本地存储 |
| 费用 | 有免费额度,超出收费 | 完全免费 |
| 响应速度 | 依赖网络延迟 | 本地响应快 |
| 模型选择 | 平台提供的模型 | 可选择开源模型 |
适合场景:
- 公司内部系统,不方便把数据发送到外部
- 个人学习研究,想怎么玩怎么玩
- 对响应速度有较高要求的生产环境
- 不想花钱买 API 服务
二、Ollama 核心概念
2.1 什么是 Ollama?
Ollama 是一个用于在本地运行大语言模型的工具。它的特点是:
- 安装简单(Windows/Mac/Linux 都有客户端)
- 支持的主流模型:Llama、Qwen、DeepSeek、Codellama 等
- 不用配置显卡驱动,下载就能用(会自动调用本地GPU)
- 通过简单的命令行就能启动模型服务
2.2 Ollama 工作原理
┌─────────────────────────────────────┐
│ 你自己的电脑 │
│ ┌──────────────────────────────┐ │
│ │ Ollama 运行环境 │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ Qwen/Llama 模型文件 │ │ │
│ │ │ (几GB到几十GB不等) │ │ │
│ │ └────────────────────────┘ │ │
│ │ ↓ │ │
│ │ 提供本地 API │ │
│ │ http://localhost:11434 │ │
│ └──────────────────────────────┘ │
│ │
└─────────────────────────────────────┘
- 模型文件存在本地硬盘
- Ollama 启动一个本地 API 服务(默认端口 11434)
- 我们的 Java 程序通过 HTTP 调用这个本地服务
- 数据完全不需要出去
2.3 Spring AI 的 Ollama 支持
Spring AI 提供了对 Ollama 的原生支持,通过 spring-ai-ollama-starter 依赖即可接入。
关键配置项:
spring.ai.ollama.base-url:Ollama 服务的地址spring.ai.ollama.chat.options.model:要使用的模型名称
三、Ollama 项目详解
3.1 项目结构
SAA-02Ollama/
├── pom.xml
├── src/main/
│ ├── java/com/atguigu/study/
│ │ ├── controller/
│ │ │ └── OllamaController.java # 控制器
│ │ └── Saa02OllamaApplication.java # 启动类
│ └── resources/
│ └── application.yml # 配置
3.2 pom.xml 依赖
<!-- 第一章的依赖,我们继续保留 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- 新增:Ollama 的 Starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-starter</artifactId>
</dependency>
💡 提示:这里同时保留了阿里云和 Ollama 的依赖,意味着我们可以同时使用两种 AI 服务!开发时可以灵活切换。
3.3 application.yml 配置
server:
port: 8002
# ============ Ollama 配置(本地模型)============
spring:
ai:
ollama:
# 告诉 Spring AI 去哪里找 Ollama 服务
base-url: http://localhost:11434
chat:
# 选择要使用的模型名称(启动 Ollama 时看到的就是这个)
options:
model: qwen2.5:0.5b
# 不验证 SSL 证书(本地开发用)
verifySsl: false
⚠️ 大坑注意:
- 确保你的电脑上已经安装了 Ollama 并启动了服务
- 通过
ollama list命令查看已下载的模型名称- 如果还没安装,去 https://ollama.com 下载安装
3.4 控制层代码
package com.atguigu.study.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
/**
* 本章要点:Spring AI 中如何区分不同的 ChatModel 实现
*
* 当项目中注入了多个 ChatModel 时,需要通过 @Qualifier 指定注入哪一个
*/
@RestController
public class OllamaController
{
// ========== @Qualifier 的作用 ==========
// 当只有一个 ChatModel 时,Spring 会自动注入
// 但如果同时有阿里云和 Ollama 两个实现,就需要指定名称
// 使用 @Qualifier("ollamaChatModel") 明确指定注入的是 Ollama 的模型
@Resource
@Qualifier("ollamaChatModel")
private ChatModel chatModel;
/**
* 普通调用:发送消息,获取完整回复
*
* 接口地址:http://localhost:8002/ollama/chat?msg=你是谁
*
* @param msg 用户发送的消息
* @return AI 的回复
*/
@GetMapping("/ollama/chat")
public String chat(@RequestParam(name = "msg") String msg)
{
// 调用本地 Ollama 模型
String result = chatModel.call(msg);
System.out.println("---结果:" + result);
return result;
}
/**
* 流式调用:逐字返回回答
*
* 接口地址:http://localhost:8002/ollama/streamchat?msg=用Java写个冒泡排序
*/
@GetMapping("/ollama/streamchat")
public Flux<String> streamchat(@RequestParam(name = "msg", defaultValue = "你是谁") String msg)
{
// 流式调用本地模型,效果和阿里云一模一样
return chatModel.stream(msg);
}
}
3.5 @Qualifier 注解详解
这是本章的一个技术重点,让我们详细解释:
// 场景:你的项目中注入了多个 ChatModel 实现
//
// 阿里云百炼 → DashScopeChatModel(bean名称默认是 "dashScopeChatModel")
// Ollama → OllamaChatModel(bean名称默认是 "ollamaChatModel")
//
// 问题:@Resource 注入时,Spring 不知道你要哪个!
// 解决:使用 @Qualifier 指定具体的 bean 名称
@Resource // 不指定?可能报错或注入错误的bean
@Qualifier("ollamaChatModel") // 明确指定:我就要 Ollama 的这个
private ChatModel chatModel;
Bean 名称的命名规则:
- 类名的首字母小写作为默认名称
OllamaChatModel→ollamaChatModelDashScopeChatModel→dashScopeChatModel
3.5.1 如果不写 @Qualifier 会怎样?
这是很多初学者容易产生误解的地方。
如果你这样写:
@Resource
private ChatModel chatModel;
Spring 会尝试从容器里找一个可以注入的 ChatModel Bean。
这时要分三种情况来看:
情况 1:容器里只有一个 ChatModel Bean
比如项目里只有 Ollama 一个模型实现,那么不写 @Qualifier 也没有问题,因为 Spring 只有一个候选对象可以注入。
情况 2:容器里有多个 ChatModel Bean
比如同时存在:
ollamaChatModeldashScopeChatModel
这时如果你不指定,Spring 往往会不知道该选哪一个。最常见的结果是:
No qualifying bean of type 'org.springframework.ai.chat.model.ChatModel' available:
expected single matching bean but found 2
也就是说,更常见的情况不是“悄悄注入错了”,而是“因为候选者太多直接报错”。
情况 3:多个 ChatModel 中有一个被标记为 @Primary
如果某个 ChatModel Bean 被标记成了主 Bean,例如 DashScope 那个被标记了 @Primary,那在不写 @Qualifier 时,Spring 就会优先选中它。
这时就真的有可能出现这样的情况:
- 你以为自己在调用 Ollama
- 实际上注入进去的是 DashScope 的
ChatModel
所以从结果上说:
不写
@Qualifier时,确实有可能注入到 DashScope,但前提是 Spring 最终能成功选中它;否则更常见的是因为多个候选 Bean 冲突而直接报错。
3.5.2 @Qualifier 到底在干什么?
它的本质作用就是:在多个同类型 Bean 中,明确点名我要哪一个。
@Resource
@Qualifier("ollamaChatModel")
private ChatModel chatModel;
这段代码等于在告诉 Spring:
我知道容器里可能有多个
ChatModel,但我不要你猜,我就要名字叫ollamaChatModel的那个。
所以它非常适合这种场景:
- 一个项目同时接入多个模型服务
- 多个实现类都实现了同一个接口
- 你希望某个 Controller / Service 明确绑定某一个具体实现
3.5.3 @Resource、@Autowired 和 @Qualifier 的关系
这里顺手也补一个很重要的知识点。
@Autowired 默认更偏向按类型注入,所以当容器里有多个 ChatModel 时,通常更容易出现歧义,需要配合 @Qualifier 使用:
@Autowired
@Qualifier("ollamaChatModel")
private ChatModel chatModel;
而 @Resource 默认会优先按名字找,再按类型找。但为了让语义更清晰、代码更稳定,在多模型场景下依然建议显式写上 @Qualifier,避免 Spring 自动匹配时产生歧义。
3.5.4 一句话总结
当项目里只有一个
ChatModel时,@Qualifier可以不写;一旦项目里同时存在 Ollama、DashScope、OpenAI 等多个模型实现,最好显式指定 Bean 名称,否则要么报冲突错误,要么在特殊情况下被注入到并不是你想要的那个实现。
四、Ollama 安装与启动指南
4.1 安装OLLAMA
Windows 用户:
- 打开 https://ollama.com
- 点击 Download for Windows
- 下载并安装 OLLAMASetup.exe
Mac 用户:
brew install ollama
Linux 用户:
curl -fsSL https://ollama.com/install.sh | sh
4.2 下载模型
安装完成后,在终端(CMD/PowerShell/Terminal)中运行:
# 查看可用的模型列表
ollama list
# 常用的模型(按体积从小到大)
ollama pull qwen2.5:0.5b # 阿里 Qwen,较小,几百MB
ollama pull qwen2.5:3b # 中等大小,1-2GB
ollama pull llama3 # Meta Llama 3
ollama pull codellama # 编程专用模型
4.3 启动服务
# 启动 Ollama 后台服务
ollama serve
# 如果是第一次使用某个模型,它会自动下载
# 启动成功后,默认监听 http://localhost:11434
五、测试验证
5.1 启动项目
- 确保 Ollama 已经在运行(
ollama serve) - 在 IDEA 中运行
Saa02OllamaApplication - 看到启动成功后开始测试
5.2 测试接口
# 普通对话 - 测试本地模型
GET http://localhost:8002/ollama/chat?msg=用Python打印HelloWorld
# 流式对话 - 观察打字效果
GET http://localhost:8002/ollama/streamchat?msg=什么是多线程
5.3 对比测试
如果你同时启动了 SAA-01 项目,可以对比一下:
- 阿里云响应时间 vs Ollama 响应时间
- 回答质量有没有明显差异(通常阿里云付费版质量更好)
六、本章小结
| 概念 | 说明 |
|---|---|
| Ollama | 本地大模型运行框架 |
| @Qualifier | 当有多个同名Bean时,用于精确指定注入哪一个 |
| Flux | 响应式流,用于流式输出效果 |
| 本地API | Ollama 默认监听 localhost:11434 |
本章重点:
- 理解为什么需要本地部署大模型
- 掌握 Ollama 的安装和基本使用
- 理解 Spring AI 中多 Bean 情况下的注入方式
下章剧透(s03):
了解了两种调用远程/本地模型的方式后,下一章我们将学习 Spring AI 中的两个核心API:
ChatModel和ChatClient的区别与使用场景。
💡 TIP:Spring AI 原生 vs Spring AI Alibaba 的 Ollama 支持
本章我们使用的是 Spring AI 原生的 Ollama 支持(通过 spring-ai-ollama-starter),而不是 Spring AI Alibaba 提供的。
两者对比:
| 特性 | Spring AI 原生 Ollama | Spring AI Alibaba |
|---|---|---|
| 依赖 | spring-ai-ollama-starter |
需自行配置 |
| 模型支持 | Ollama 官方所有模型 | 仅支持部分模型 |
| 更新频率 | 跟随 Ollama 官方 | 与阿里云服务同步 |
为什么课程用 Spring AI 原生?
因为 Ollama 本身是独立项目,使用 Spring AI 原生支持更纯粹。但实际上,你也可以把 Ollama 看作另一个"AI _provider",完全可以共存于同一个项目中(就像我们的 Demo 同时支持阿里云和 Ollama)。
📝 编辑者:Flittly
📅 更新时间:2026年3月
🔗 相关资源:Ollama 官网 | Spring AI Ollama 文档