跳到主要内容
Java AI java 算法
Spring AI 实战:基于 Ollama 构建离线私有化 AI 服务 介绍基于 Ollama 和 Spring AI 构建离线私有化 AI 服务的完整方案。涵盖 Ollama 本地部署、模型量化优化、Spring AI 深度对接及自定义 ModelClient 实现。通过 Chroma DB 构建本地向量数据库,实现无外网依赖的 RAG 知识库问答。提供资源占用控制、高可用配置及生产环境监控建议,解决第三方 API 成本、合规风险及数据安全问题,适合金融政务等敏感行业落地。
不知所云 发布于 2026/4/5 更新于 2026/5/20 25 浏览前言
作为企业级开发者,在使用大模型时常常面临三大痛点:依赖第三方 API 密钥导致的成本不可控 、外网依赖导致的合规风险 、用户数据上传第三方平台导致的安全隐患 。尤其是金融、政务等敏感行业,离线私有化部署几乎是硬性要求。
本文基于 Ollama+Spring AI 完成了一套离线 AI 服务的落地,从模型拉取、量化优化到 RAG 知识库构建全程无外网依赖,彻底摆脱了 API 密钥的束缚。本文将从实战角度,完整拆解离线 AI 服务的开发全流程:包含 Ollama 部署、Spring AI 深度对接、模型量化优化、离线 RAG 知识库落地,所有代码均经过生产环境验证,同时结合可视化图表清晰呈现核心逻辑,希望能为企业级离线 AI 部署提供可落地的参考方案。
一、项目背景与技术选型
1.1 核心痛点与解决方案
业务痛点 解决方案 技术选型 依赖第三方 API 密钥,成本不可控 本地部署开源大模型,彻底脱离 API 密钥 Ollama(轻量模型运行时) 外网依赖导致合规风险 全程离线部署,模型与数据均在本地 Spring AI(AI 能力封装)+ Chroma DB(本地向量库) 大模型资源占用过高,无法在普通服务器运行 模型量化压缩,平衡精度与资源占用 Ollama 量化技术(Q4_K_M 等级别) 离线场景下无法实现知识库问答 构建本地 RAG 知识库,文档与向量均存储在本地 LangChain4j(RAG 框架)+ Chroma DB(本地向量库)
1.2 整体技术架构
以下是离线 AI 服务的核心架构图,清晰呈现各模块的交互逻辑:
1.3 技术栈选型
结合企业级离线部署需求,最终选型如下:
技术领域 选型 选型理由 模型运行时 Ollama 0.1.48 轻量、支持一键拉取量化模型、自动管理显存 / CPU 资源 AI 框架 Spring AI 0.8.1 + LangChain4j 0.27.0 Spring AI 原生适配 Spring 生态,LangChain4j 提供成熟的 RAG 能力 向量数据库 Chroma DB 0.4.24 纯 Java 实现、本地文件存储、无需额外依赖、适配离线场景 模型选择 Llama3 8B Q4_K_M + Qwen 7B Q4_K_M 平衡精度与资源占用,适合 16GB 内存服务器部署 部署方式 Docker + 裸金属 Docker 保证环境一致性,裸金属提升资源利用率
二、Ollama 本地部署与核心配置
2.1 Ollama 安装与环境验证
2.1.1 安装步骤(Linux/macOS/Windows 通用)
curl -fsSL https://ollama.com/install.sh | sh
ollama --version
2.1.2 启动与端口验证
ollama serve
netstat -tulpn | grep 11434
2.2 模型拉取与量化级别选择 Ollama 支持一键拉取量化模型,无需手动处理量化压缩,核心量化级别及适用场景如下:
量化级别 精度损失 资源占用 适用场景 Q2_K 较高 最小(8B 模型约 2.7GB) 低配置设备(8GB 内存)、对精度要求不高的场景 Q4_K_M 中等 平衡(8B 模型约 4.5GB) 16GB 内存服务器、企业级通用场景(推荐) Q5_K_M 较低 较高(8B 模型约 5.5GB) 24GB 内存服务器、对精度要求高的场景 Q8_0 极低 高(8B 模型约 8GB) 32GB 以上内存服务器、追求极致精度的场景
2.2.1 拉取量化模型(推荐 Q4_K_M)
ollama pull llama3:8b-q4_K_M
ollama pull qwen:7b-q4_K_M
ollama pull phi3:mini-q2_K
2.2.2 验证模型部署
ollama list
ollama run llama3:8b-q4_K_M "用 Java 写一个 Spring Boot Hello World"
2.3 核心参数配置(资源优化) 修改 Ollama 配置文件(/etc/ollama/config.json),优化资源占用:
{
"num_ctx" : 4096 ,
"num_gpu" : 1 ,
"num_thread" : 8 ,
"batch_size" : 512 ,
"low_vram" : true
}
💡 实战提示:若服务器无 GPU,需将 num_gpu 设为 0,强制使用 CPU 推理;若显存不足(如 16GB 显存运行 8B 模型),开启 low_vram 可显著降低显存占用。
三、Spring AI 对接 Ollama:自定义 ModelClient 实现
3.1 核心依赖引入 在 pom.xml 中添加 Spring AI 与 Ollama 的依赖:
<dependencies >
<dependency >
<groupId > org.springframework.ai</groupId >
<artifactId > spring-ai-ollama</artifactId >
<version > 0.8.1</version >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > dev.langchain4j</groupId >
<artifactId > langchain4j-spring-boot-starter</artifactId >
<version > 0.27.0</version >
</dependency >
</dependencies >
3.2 自定义 Ollama ModelClient 配置 Spring AI 原生支持 Ollama,但默认实现无法满足复杂的业务需求(如自定义上下文窗口、流式响应优化),因此需要自定义 ModelClient:
@Configuration
public class OllamaConfig {
@Value("${ollama.base-url:http://localhost:11434}")
private String baseUrl;
@Value("${ollama.model:llama3:8b-q4_K_M}")
private String model;
@Bean
public OllamaChatClient ollamaChatClient () {
OllamaApi ollamaApi = OllamaApi.builder()
.baseUrl(baseUrl)
.build();
return new OllamaChatClient (ollamaApi)
.withModel(model)
.withTemperature(0.2 )
.withTopP(0.9 )
.withNumCtx(4096 )
.withStream(true );
}
}
3.3 核心 API 实现(生成 + 流式响应)
@RestController
@RequestMapping("/api/ai")
public class AiController {
@Autowired
private OllamaChatClient ollamaChatClient;
@PostMapping("/generate")
public Result<String> generate (@RequestBody AiRequest request) {
Prompt prompt = new Prompt (new UserMessage (request.getPrompt()));
AiResponse response = ollamaChatClient.generate(prompt);
return Result.success(response.getGeneration().getText());
}
@PostMapping("/stream")
public SseEmitter streamGenerate (@RequestBody AiRequest request) {
SseEmitter emitter = new SseEmitter (60000L );
Prompt prompt = new Prompt (new UserMessage (request.getPrompt()));
ollamaChatClient.stream(prompt).subscribe(
chunk -> {
try {
emitter.send(chunk.getGeneration().getText());
} catch (IOException e) {
emitter.completeWithError(e);
}
},
emitter::completeWithError,
emitter::complete
);
return emitter;
}
}
@Data
public class AiRequest {
private String prompt;
private String model;
}
3.4 接口验证 通过 Postman 调用接口,验证离线 AI 服务正常运行:
curl -X POST http://localhost:8080/api/ai/generate \
-H "Content-Type: application/json" \
-d '{"prompt":"用 Java 写一个 Spring AI 调用 Ollama 的示例代码"}'
curl -X POST http://localhost:8080/api/ai/stream \
-H "Content-Type: application/json" \
-d '{"prompt":"详细介绍 Spring AI 的核心功能"}'
四、模型优化:量化压缩与资源占用控制
4.1 量化级别实战对比 在 16GB 内存服务器上,不同量化级别 Llama3 8B 模型的资源占用对比:
量化级别 显存占用 CPU 占用 响应速度(生成 1000 字) Q2_K 2.7GB 40% 12 秒 Q4_K_M 4.5GB 60% 8 秒 Q5_K_M 5.5GB 70% 6 秒 Q8_0 8GB 80% 5 秒
💡 实战结论:Q4_K_M 是性价比最高的选择,在 16GB 内存服务器上可稳定运行,响应速度与精度达到平衡;若追求极致性能,可选择 Q5_K_M;若服务器内存不足 8GB,建议选择 Phi-3 Mini Q2_K。
4.2 资源占用优化技巧
CPU 绑定 :在 Ollama 配置中设置 num_thread 与服务器核心数匹配(如 8 核服务器设为 8),避免线程上下文切换;
显存限制 :开启 low_vram 模式,强制模型使用 CPU 推理,适合无 GPU 或显存不足的场景;
上下文窗口调整 :根据业务需求调整 num_ctx(默认 4096),减少不必要的内存占用;
批量处理优化 :设置 batch_size 为 512 或 1024,提升并发请求的处理效率。
4.3 性能压测与调优 使用 JMeter 对生成接口进行压测,10 并发场景下的性能表现:
指标 Q4_K_M Q5_K_M 平均响应时间 1.2s 0.9s QPS 8.3 11.1 错误率 0% 0%
🚨 踩坑提示:若压测时出现 OOM 错误,需检查 num_ctx 是否过大,或降低量化级别;若出现响应超时,需调整 batch_size 或增加 CPU 线程数。
五、实战:离线 RAG 知识库部署(无外网环境适配)
5.1 RAG 核心流程
5.2 离线 RAG 核心配置
5.2.1 向量数据库(Chroma DB)本地部署 Chroma DB 支持纯 Java 本地部署,无需额外依赖,配置如下:
@Configuration
public class ChromaConfig {
@Bean
public Chroma chroma () {
return Chroma.builder()
.persistDirectory("./chroma-data" )
.build();
}
}
5.2.2 文档导入与向量生成
@Service
public class KnowledgeBaseService {
@Autowired
private Chroma chroma;
@Autowired
private OllamaEmbeddingClient embeddingClient;
public void importDocument (String filePath) throws IOException {
File file = new File (filePath);
String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
List<String> chunks = RecursiveCharacterTextSplitter.builder()
.chunkSize(1000 )
.chunkOverlap(200 )
.build()
.split(content);
List<Embedding> embeddings = embeddingClient.embed(chunks);
for (int i = 0 ; i < chunks.size(); i++) {
chroma.add(
CollectionUtils.singletonList(UUID.randomUUID().toString()),
CollectionUtils.singletonList(chunks.get(i)),
embeddings.get(i).getEmbedding()
);
}
}
}
5.2.3 RAG 问答接口实现
@Service
public class RagQAService {
@Autowired
private Chroma chroma;
@Autowired
private OllamaEmbeddingClient embeddingClient;
@Autowired
private OllamaChatClient ollamaChatClient;
public String qa (String question) {
Embedding questionEmbedding = embeddingClient.embed(question);
List<Document> documents = chroma.query(
questionEmbedding.getEmbedding(),
3 ,
null ,
null
);
String context = documents.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n\n" ));
String prompt = "请基于以下上下文回答问题,若上下文没有相关信息,直接回答暂无相关信息:\n上下文:%s\n问题:%s" .formatted(context, question);
Prompt aiPrompt = new Prompt (new UserMessage (prompt));
AiResponse response = ollamaChatClient.generate(aiPrompt);
return response.getGeneration().getText();
}
}
5.3 无外网环境适配
模型离线包导入 :若服务器无外网,可在有网环境下载模型离线包(ollama pull llama3:8b-q4_K_M --output llama3-8b-q4_K_M.tar),然后在离线服务器上导入(ollama create llama3:8b-q4_K_M -f llama3-8b-q4_K_M.tar);
文档离线导入 :将本地文档上传到服务器,通过 importDocument 接口导入到知识库;
向量存储本地化 :Chroma DB 的向量存储在本地文件(./chroma-data),无需依赖云服务。
六、生产环境落地:高可用与监控
6.1 高可用配置
多实例部署 :通过 Docker Compose 部署多个 Ollama 实例,结合 Nginx 负载均衡,提升并发能力;
模型热切换 :支持动态切换模型(如 Llama3/Qwen),通过 API 参数指定模型;
容错机制 :为大模型调用添加重试、熔断(Resilience4j),避免服务雪崩。
6.2 监控与告警 整合 Prometheus+Grafana 实现服务监控,核心监控指标:
Ollama 模型调用 QPS、响应时间、错误率;
服务器 CPU、内存、显存占用;
RAG 知识库检索召回率、向量生成速度。
6.3 日志排查 为服务添加完整的日志体系,记录模型调用、RAG 检索、向量生成的详细日志,方便排查问题:
@Slf4j
@Service
public class AiCodeService {
public String generateCode (String requirement) {
log.info("生成代码请求:{}" , requirement);
try {
Prompt prompt = new Prompt (new UserMessage (requirement));
AiResponse response = ollamaChatClient.generate(prompt);
log.info("生成代码响应:{}" , response.getGeneration().getText());
return response.getGeneration().getText();
} catch (Exception e) {
log.error("生成代码失败" , e);
throw new BusinessException ("生成代码失败:" + e.getMessage());
}
}
}
七、实战踩坑与进阶规划
7.1 常见问题与解决方案 问题场景 根因分析 解决方案 Ollama 拉取模型失败 网络问题或模型名称错误 1. 检查网络连接;2. 使用 ollama search 验证模型名称;3. 导入离线模型包 Spring AI 调用超时 模型推理时间过长或资源不足 1. 降低量化级别;2. 增加 CPU 线程数;3. 开启流式响应 RAG 召回率低 文档分割不合理或向量模型精度不足 1. 调整文档分割大小(如 1000 字符 / 块);2. 使用更高精度的嵌入模型(如 Q5_K_M);3. 增加检索 TopN 数量 服务器显存不足 模型占用过高或上下文窗口过大 1. 开启 low_vram 模式;2. 降低 num_ctx;3. 选择更小的模型(如 Phi-3 Mini)
7.2 进阶规划
模型微调 :基于 Ollama 实现模型微调,适配企业专属业务场景;
多模型融合 :支持 Llama3/Qwen/Phi3 多模型调用,根据业务需求动态选择;
知识库增量更新 :支持文档增量导入与向量更新,无需全量重建;
分布式部署 :通过 Kubernetes 部署多实例,实现弹性扩缩容;
国产化适配 :适配文心一言、通义千问等国产大模型,满足信创需求。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online