有人问,能不能本地运行大模型啊? 答案是:有。Ollama + Open WebUI 是目前最成熟的本地大模型运行方案。本文从零开始,带你在一台普通开发机上跑起自己的 LLM 服务。
一、Ollama 是什么
Ollama 是一个开源的本地大模型运行框架,核心功能只有两个:
- 模型管理 —— 一键下载、运行、切换各种开源模型
- 兼容 API —— 提供与 OpenAI 格式兼容的 HTTP API
这意味着你本地跑起来的模型,可以直接替换掉代码里的 openai.chat.completions.create 调用,只需换掉 base URL。
为什么要用 Ollama 而不是直接跑模型
方案 | 优点 | 缺点
------ | ------ | ------
直接用 Python 加载模型 | 灵活,可调底层参数 | 需要写大量粘合代码,GPU 显存管理麻烦
Ollama | 一行命令搞定,API 兼容 OpenAI | 对底层控制力稍弱
vLLM / TGI | 生产级高性能推理 | 配置复杂,资源要求高
对于个人开发者和中小团队,Ollama 是最佳平衡点。
二、安装与配置
2.1 安装 Ollama
Linux(推荐):
curl -fsSL ollama.com/install.sh | sh
安装完成后检查版本:
ollama --version
ollama version 0.5.12
macOS / Windows: 从 ollama.com/download 下载安装包,双击安装。
2.2 首次运行模型
Ollama 的核心命令只有一个 ollama run。以下载和运行 Qwen2.5(千问)的 7B 模型为例:
ollama run qwen2.5:7b
第一次运行会自动下载模型(约 4.7GB),下载完成后进入交互式对话模式:
模型 | 参数 | 显存需求 | 中文能力 | 适用场景
------ | ------ | ---------- | ---------- | ----------
qwen2.5:7b | 7B | 4-6GB | ★★★★★ | 日常开发测试,推荐首选
llama3.1:8b | 8B | 5-7GB | ★★★☆☆ | 英文能力强,逻辑推理好
deepseek-r1:7b | 7B | 5-6GB | ★★★★★ | 国产模型,推理链优秀
phi4:14b | 14B | 8-12GB | ★★☆☆☆ | 微软出品,代码能力突出
qwen2.5:14b | 14B | 10-12GB | ★★★★★ | 中文场景的最佳大杯选择
2.4 模型管理常见操作
列出已下载的模型
ollama list
查看模型详情
ollama show qwen2.5:7b
删除模型释放空间
ollama rm qwen2.5:7b
复制模型创建自定义版本
ollama cp qwen2.5:7b my-custom-model
拉取特定模型(不运行)
ollama pull llama3.1:8b
三、Open WebUI —— 给 Ollama 装上图形界面
Ollama 自带的命令行交互虽然能用,但体验和 ChatGPT 相差甚远。Open WebUI(原名 Ollama WebUI)是一个开源的 Web 界面,功能对标 ChatGPT Plus:
- 多轮对话管理
- Markdown 渲染(代码高亮、数学公式)
- 多模型切换
- 文件上传(图片、PDF、代码)
- 提示词模板库
- 用户权限管理(多用户场景)
3.1 使用 Docker 安装(推荐)
这是最简单的安装方式:
docker run -d --name open-webui \
-p 3000:8080 \
-v open-webui-data:/app/backend/data \
如果你不想装 Docker,也可以用 Python 直接运行:
克隆项目
git clone github.com/open-webui/…
cd open-webui
安装依赖
pip install -r requirements.txt
运行
python -m open_webui
3.3 配置与初始设置
启动后访问 http://localhost:3000:
- 注册第一个账号(自动成为管理员)
- 进入 设置 → 模型,确认 Ollama 连接状态
- 在模型选择下拉框中你应该能看到已下载的模型列表
四、通过 API 调用本地模型(Java 实战)
这是本文最核心的部分 —— 让你的 Java 代码调用本地模型。
4.1 OpenAI 兼容 API 格式
Ollama 默认在 http://localhost:11434 提供 API,格式与 OpenAI 完全兼容:
测试 API 是否可用
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5:7b",
"messages": [
{"role": "user", "content": "用 Java 写一个单例模式"}
]
}'
4.2 使用 HttpClient 调用(无框架版)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest.BodyPublishers;
public class LocalLLMClient {
private static final String BASE_URL = "http://localhost:11434/v1";
private final HttpClient httpClient;
public LocalLLMClient() {
this.httpClient = HttpClient.newHttpClient();
}
public String chat(String model, String userMessage) throws Exception {
String json = """
{
"model": "%s",
"messages": [{"role": "user", "content": "%s"}],
"temperature": 0.7,
"max_tokens": 2048
}
""".formatted(model, escapeJson(userMessage));
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/chat/completions"))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofString(json))
.build();
HttpResponse response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
}
private String escapeJson(String s) {
return s.replace("\", "\\")
.replace(""", "\"")
.replace("\n", "\n")
.replace("\r", "\r")
.replace("\t", "\t");
}
public static void main(String[] args) throws Exception {
LocalLLMClient client = new LocalLLMClient();
String result = client.chat("qwen2.5:7b",
"请用 Java 写一个线程安全的单例模式,并解释双重检查锁定的原理。");
System.out.println(result);
}
}
4.3 使用 Spring Boot + RestTemplate
如果你已经在用 Spring Boot,集成更简单:
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import java.util.List;
import java.util.Map;
@Service
public class LocalLLMService {
private final RestTemplate restTemplate;
private static final String OLLAMA_API = "http://localhost:11434/v1/chat/completions";
public LocalLLMService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public String chat(String model, String message) {
// 构建请求体
var requestBody = Map.of(
"model", model,
"messages", List.of(Map.of("role", "user", "content", message)),
"temperature", 0.7,
"max_tokens", 2048
);
var headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
var entity = new HttpEntity<>(requestBody, headers);
// 调用 API
var response = restTemplate.exchange(
OLLAMA_API,
HttpMethod.POST,
entity,
Map.class
);
// 解析响应 —— 返回值嵌套较深,逐层提取
Map<String, Object> body = response.getBody();
if (body != null && body.containsKey("choices")) {
var choices = (List<Map<String, Object>>) body.get("choices");
if (!choices.isEmpty()) {
var messageObj = (Map<String, Object>) choices.get(0).get("message");
return (String) messageObj.get("content");
}
}
return "";
}
}
4.4 使用 Spring AI 统一抽象
如果你的项目已经用了 Spring AI,切换成本几乎为零。只需改 application.yml:
spring:
ai:
openai:
base-url: http://localhost:11434/v1
api-key: ollama # Ollama 不验证 key,填任意值即可
chat:
options:
model: qwen2.5:7b
temperature: 0.7
代码层面完全不需要改动:
@Component
public class AIService {
@Autowired
private ChatClient chatClient;
public String ask(String question) {
return chatClient.prompt()
.user(question)
.call()
.content();
}
}
原理: Spring AI 的 Open AI 适配器只依赖 OpenAI 兼容的 API 格式,而 Ollama 恰好完美兼容。你可以在本地开发和测试时用 Ollama,上线后把 base-url 切回真正的 OpenAI,代码一行不改。
五、进阶:自定义模型与性能调优
5.1 创建自定义 Modelfile
Ollama 支持通过 Modelfile 自定义模型参数,类似于 Dockerfile 之于 Docker:
FROM qwen2.5:7b
设置系统提示词,定制模型人设
SYSTEM """你是一名资深的 Java 架构师,精通 Spring Boot 和微服务。
请用中文回答所有问题,给出可直接运行的代码示例。"""
调整推理参数
PARAMETER temperature 0.3
PARAMETER top_p 0.9
PARAMETER stop ""
构建自定义模型:
ollama create java-architect -f Modelfile
ollama run java-architect
5.2 提高推理速度
影响 Ollama 推理速度的三大因素:
- 量化级别(Quantization):
qwen2.5:7b默认是 Q4_K_M 量化。如果需要更快且显存更小,选择qwen2.5:7b:q3_K_M(3bit 量化);如果需要更高精度,选择qwen2.5:7b:q8_0。 - 上下文长度(Context Length):默认 2048,通过
--num-ctx调整:
ollama run qwen2.5:7b --num-ctx 8192
更大的上下文消耗更多显存。
- 批处理大小(Batch Size):GPU 推理时增大 batch 可提高吞吐:
ollama run qwen2.5:7b --num-batch 512
5.3 GPU vs CPU 推理
查看当前推理模式:
ollama ps
如果 GPU 不可用,Ollama 会自动回退到 CPU。强制使用 CPU(调试用):
OLLAMA_INTEL_GPU=0 ollama run qwen2.5:7b
性能对比参考(7B 模型,M2 MacBook Air):
模式 | 生成速度 | 提问响应
------ | ---------- | ----------
GPU (MPS) | 25-35 token/s | 即时
CPU (16GB) | 4-7 token/s | 2-3 秒延迟
CPU + 16GB RAM + 8 核 | 5-8 token/s | 1-2 秒延迟
六、常见问题排查
6.1 Ollama 启动失败
查看日志
journalctl -u ollama -f
重新启动
systemctl restart ollama
6.2 API 连接被拒绝
检查端口是否监听
ss -tlnp | grep 11434
检查防火墙
systemctl status ufw
或
firewall-cmd --list-all
6.3 Docker 容器无法连接 Ollama
方案一:使用 host 网络模式(推荐)
docker run --network host ...
方案二:将 Ollama 绑定到 0.0.0.0
OLLAMA_HOST=0.0.0.0 ollama serve
然后容器内用宿主机 IP 连接
6.4 模型回答乱码 / 中英文混杂
通常是因为提示词没有明确指定语言:
// 在 system prompt 中明确指定
SYSTEM """你是一个中文助手,请始终用中文回答。"""
或者在每次调用时强调:
String prompt = "请用中文回答:Spring Boot 的自动配置原理是什么?";
七、总结与下一步
本文从零开始搭建了一套完整的本地大模型运行环境:
- ✅ Ollama 负责模型管理与 API 服务
- ✅ Open WebUI 提供类 ChatGPT 的图形界面
- ✅ Java 代码 通过 OpenAI 兼容 API 调用本地模型
跟 API 调用相比,本地部署的好处:
- 零 API 费用,无限调用
- 数据不出本机,隐私安全
- 可离线使用
- 延迟更低(无网络开销)
代价:
-
需要一定的硬件资源(至少 4GB 显存 / 8GB 内存)
-
模型能力弱于 GPT-4/Claude-3.5 等顶级闭源模型
-
需要自己维护模型版本
注:文章由AI生成,请注意甄别真实性