跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaAIjava算法

Spring AI 实战:基于 Ollama 构建离线私有化 AI 服务

介绍基于 Ollama 和 Spring AI 构建离线私有化 AI 服务的完整方案。涵盖 Ollama 本地部署、模型量化优化、Spring AI 深度对接及自定义 ModelClient 实现。通过 Chroma DB 构建本地向量数据库,实现无外网依赖的 RAG 知识库问答。提供资源占用控制、高可用配置及生产环境监控建议,解决第三方 API 成本、合规风险及数据安全问题,适合金融政务等敏感行业落地。

不知所云发布于 2026/4/5更新于 2026/5/2025 浏览
Spring AI 实战:基于 Ollama 构建离线私有化 AI 服务

前言

作为企业级开发者,在使用大模型时常常面临三大痛点:依赖第三方 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.0Spring 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 通用)
# Linux/macOS 一键安装 curl -fsSL https://ollama.com/install.sh | sh # Windows:下载安装包并执行(https://ollama.com/download/windows) # 验证安装 ollama --version # 输出:ollama version 0.1.48
2.1.2 启动与端口验证
# 启动 Ollama 服务(默认端口 11434)
ollama serve
# 验证端口监听
netstat -tulpn | grep 11434
# 输出:tcp 0 0 127.0.0.1:11434 0.0.0.0:* LISTEN 1234/ollama
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)
# 拉取 Llama3 8B Q4_K_M(平衡精度与性能)
ollama pull llama3:8b-q4_K_M
# 拉取 Qwen 7B Q4_K_M(国产模型,适配中文场景)
ollama pull qwen:7b-q4_K_M
# 拉取 Phi-3 Mini Q2_K(极致轻量化,适合开发测试)
ollama pull phi3:mini-q2_K
2.2.2 验证模型部署
# 查看本地模型列表
ollama list
# 输出:
# NAME ID SIZE MODIFIED
# llama3:8b-q4_K_M 78e26419b446 4.7 GB 2 minutes ago
# 命令行交互验证
ollama run llama3:8b-q4_K_M "用 Java 写一个 Spring Boot Hello World"
# 输出完整的 Java 代码,验证模型正常运行
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>
    <!-- Spring AI 核心依赖 -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-ollama</artifactId>
        <version>0.8.1</version>
    </dependency>
    <!-- Spring Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- LangChain4j(RAG 支持) -->
    <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:

/**
 * 自定义 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) // 与 Ollama 配置保持一致
                .withStream(true); // 开启流式响应
    }
}
3.3 核心 API 实现(生成 + 流式响应)
/**
 * 离线 AI 核心接口
 */
@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); // 超时时间 60 秒
        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_K2.7GB40%12 秒
Q4_K_M4.5GB60%8 秒
Q5_K_M5.5GB70%6 秒
Q8_08GB80%5 秒

💡 实战结论:Q4_K_M 是性价比最高的选择,在 16GB 内存服务器上可稳定运行,响应速度与精度达到平衡;若追求极致性能,可选择 Q5_K_M;若服务器内存不足 8GB,建议选择 Phi-3 Mini Q2_K。

4.2 资源占用优化技巧
  1. CPU 绑定:在 Ollama 配置中设置 num_thread 与服务器核心数匹配(如 8 核服务器设为 8),避免线程上下文切换;
  2. 显存限制:开启 low_vram 模式,强制模型使用 CPU 推理,适合无 GPU 或显存不足的场景;
  3. 上下文窗口调整:根据业务需求调整 num_ctx(默认 4096),减少不必要的内存占用;
  4. 批量处理优化:设置 batch_size 为 512 或 1024,提升并发请求的处理效率。
4.3 性能压测与调优

使用 JMeter 对生成接口进行压测,10 并发场景下的性能表现:

指标Q4_K_MQ5_K_M
平均响应时间1.2s0.9s
QPS8.311.1
错误率0%0%

🚨 踩坑提示:若压测时出现 OOM 错误,需检查 num_ctx 是否过大,或降低量化级别;若出现响应超时,需调整 batch_size 或增加 CPU 线程数。

五、实战:离线 RAG 知识库部署(无外网环境适配)

5.1 RAG 核心流程

文章配图

5.2 离线 RAG 核心配置
5.2.1 向量数据库(Chroma DB)本地部署

Chroma DB 支持纯 Java 本地部署,无需额外依赖,配置如下:

/**
 * Chroma DB 本地配置
 */
@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 {
        // 1. 解析本地文档(支持 PDF/Word/Markdown)
        File file = new File(filePath);
        String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        
        // 2. 分割文档(按段落分割,避免上下文过长)
        List<String> chunks = RecursiveCharacterTextSplitter.builder()
                .chunkSize(1000)
                .chunkOverlap(200)
                .build()
                .split(content);
        
        // 3. 生成向量并存储
        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 问答接口实现
/**
 * RAG 问答核心服务
 */
@Service
public class RagQAService {
    @Autowired
    private Chroma chroma;
    
    @Autowired
    private OllamaEmbeddingClient embeddingClient;
    
    @Autowired
    private OllamaChatClient ollamaChatClient;

    /**
     * 基于知识库的问答
     */
    public String qa(String question) {
        // 1. 问题向量化
        Embedding questionEmbedding = embeddingClient.embed(question);
        
        // 2. 向量检索(返回 Top3 相关文档)
        List<Document> documents = chroma.query(
            questionEmbedding.getEmbedding(),
            3,
            null,
            null
        );
        
        // 3. 拼接上下文 Prompt
        String context = documents.stream()
                .map(Document::getContent)
                .collect(Collectors.joining("\n\n"));
        String prompt = "请基于以下上下文回答问题,若上下文没有相关信息,直接回答暂无相关信息:\n上下文:%s\n问题:%s".formatted(context, question);
        
        // 4. 调用大模型生成回答
        Prompt aiPrompt = new Prompt(new UserMessage(prompt));
        AiResponse response = ollamaChatClient.generate(aiPrompt);
        return response.getGeneration().getText();
    }
}
5.3 无外网环境适配
  1. 模型离线包导入:若服务器无外网,可在有网环境下载模型离线包(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);
  2. 文档离线导入:将本地文档上传到服务器,通过 importDocument 接口导入到知识库;
  3. 向量存储本地化:Chroma DB 的向量存储在本地文件(./chroma-data),无需依赖云服务。

六、生产环境落地:高可用与监控

6.1 高可用配置
  1. 多实例部署:通过 Docker Compose 部署多个 Ollama 实例,结合 Nginx 负载均衡,提升并发能力;
  2. 模型热切换:支持动态切换模型(如 Llama3/Qwen),通过 API 参数指定模型;
  3. 容错机制:为大模型调用添加重试、熔断(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 进阶规划
  1. 模型微调:基于 Ollama 实现模型微调,适配企业专属业务场景;
  2. 多模型融合:支持 Llama3/Qwen/Phi3 多模型调用,根据业务需求动态选择;
  3. 知识库增量更新:支持文档增量导入与向量更新,无需全量重建;
  4. 分布式部署:通过 Kubernetes 部署多实例,实现弹性扩缩容;
  5. 国产化适配:适配文心一言、通义千问等国产大模型,满足信创需求。

目录

  1. 前言
  2. 一、项目背景与技术选型
  3. 1.1 核心痛点与解决方案
  4. 1.2 整体技术架构
  5. 1.3 技术栈选型
  6. 二、Ollama 本地部署与核心配置
  7. 2.1 Ollama 安装与环境验证
  8. 2.1.1 安装步骤(Linux/macOS/Windows 通用)
  9. Linux/macOS 一键安装
  10. Windows:下载安装包并执行(https://ollama.com/download/windows)
  11. 验证安装
  12. 输出:ollama version 0.1.48
  13. 2.1.2 启动与端口验证
  14. 启动 Ollama 服务(默认端口 11434)
  15. 验证端口监听
  16. 输出:tcp 0 0 127.0.0.1:11434 0.0.0.0:* LISTEN 1234/ollama
  17. 2.2 模型拉取与量化级别选择
  18. 2.2.1 拉取量化模型(推荐 Q4KM)
  19. 拉取 Llama3 8B Q4KM(平衡精度与性能)
  20. 拉取 Qwen 7B Q4KM(国产模型,适配中文场景)
  21. 拉取 Phi-3 Mini Q2_K(极致轻量化,适合开发测试)
  22. 2.2.2 验证模型部署
  23. 查看本地模型列表
  24. 输出:
  25. NAME ID SIZE MODIFIED
  26. llama3:8b-q4KM 78e26419b446 4.7 GB 2 minutes ago
  27. 命令行交互验证
  28. 输出完整的 Java 代码,验证模型正常运行
  29. 2.3 核心参数配置(资源优化)
  30. 三、Spring AI 对接 Ollama:自定义 ModelClient 实现
  31. 3.1 核心依赖引入
  32. 3.2 自定义 Ollama ModelClient 配置
  33. 3.3 核心 API 实现(生成 + 流式响应)
  34. 3.4 接口验证
  35. 同步生成接口
  36. 流式生成接口
  37. 四、模型优化:量化压缩与资源占用控制
  38. 4.1 量化级别实战对比
  39. 4.2 资源占用优化技巧
  40. 4.3 性能压测与调优
  41. 五、实战:离线 RAG 知识库部署(无外网环境适配)
  42. 5.1 RAG 核心流程
  43. 5.2 离线 RAG 核心配置
  44. 5.2.1 向量数据库(Chroma DB)本地部署
  45. 5.2.2 文档导入与向量生成
  46. 5.2.3 RAG 问答接口实现
  47. 5.3 无外网环境适配
  48. 六、生产环境落地:高可用与监控
  49. 6.1 高可用配置
  50. 6.2 监控与告警
  51. 6.3 日志排查
  52. 七、实战踩坑与进阶规划
  53. 7.1 常见问题与解决方案
  54. 7.2 进阶规划
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Moyin Creator(魔因漫创):AI 影视生产级全流程创作工具
  • 使用 OpenLLM 构建和部署大模型应用
  • Silly Tavern 角色卡与世界书导入教程
  • llama.cpp 重大更新:自带 Web UI,性能表现优异,本地大模型部署新方案
  • GLM-4.7-Flash 本地 AI 编码助手部署指南
  • 如何将 Android 项目上传至 GitHub
  • CentOS 7 WinSCP 普通用户上传文件无权限解决方案
  • Microi 吾码:基于 Spring Boot 的低代码微服务框架
  • AIGC 异步回调系统架构设计与实现
  • Python 实时快递物流跟踪爬虫:异步并发与智能解析
  • 主流大模型架构全景 | GPT/LLaMA/DeepSeek/Qwen 深度对比
  • Linux 信号量详解与基于环形队列的生产消费模型实现
  • Kali Linux 官方更新命令详解
  • GEO 生成式引擎优化:当 AI 成为流量入口,内容如何被看见
  • C++ vector 容器:底层原理、扩容机制与实战用法详解
  • 常见排序算法原理与实现详解
  • ToClaw 评测:不只是炫技,更是易用的桌面 AI 助手
  • Flutter 三方库 dart_webrtc 的鸿蒙化适配指南
  • C++穷举算法详解:原理、实现与应用
  • Qwen3-4B-Instruct 提示词优化与使用避坑指南

相关免费在线工具

  • 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