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

基于 Ollama 和 Spring AI 的离线私有化 AI 服务实战

介绍基于 Ollama 和 Spring AI 构建离线私有化 AI 服务的完整方案。涵盖 Ollama 本地部署、模型量化优化、Spring AI 深度对接、Chroma DB 向量库构建及 RAG 知识库落地。通过量化压缩降低资源占用,实现无外网依赖、无 API 密钥的本地大模型应用,适用于金融、政务等敏感行业场景。

山野来信发布于 2026/4/5更新于 2026/9/1092 浏览
基于 Ollama 和 Spring AI 的离线私有化 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. 国产化适配:适配文心一言、通义千问等国产大模型,满足信创需求。

本文从实战角度完整拆解了基于 Ollama+Spring AI 的离线私有化 AI 服务开发,覆盖了 Ollama 部署、Spring AI 对接、模型优化、离线 RAG 落地等核心环节,所有代码均经过生产环境验证。这套方案彻底摆脱了 API 密钥的束缚,实现了模型与数据的完全本地化,适合金融、政务等敏感行业的 AI 落地需求。

目录

  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 进阶规划

更多推荐文章

查看全部
  • AI 产品经理晋升路线图:从入门到精通的进阶指南
  • Android 面试核心技巧与关键技术点梳理
  • Python 核心语法精讲:变量、流程控制与数据结构
  • 基于 LangGraph 构建带记忆与人工干预的智能搜索机器人
  • C++ 高并发内存池实战:内存释放流程详解
  • Xilinx FPGA 外部 SPI Flash 启动时钟频率配置详解
  • Linux 信号处理:可重入函数原理与实战规范
  • 动态规划:排列与组合的区别解析
  • Python 之父 Guido Van Rossum 宣布从 Dropbox 退休
  • GitHub Copilot 接入第三方模型 API 指南
  • Stable Diffusion WebUI 启动报错:MessageFactory GetPrototype 修复方案
  • 高空长航时无人机热管理系统中抗辐照 MCU 的可靠性验证与应用
  • 基于 Web Scraper 插件的知乎评论数据抓取实战
  • AI Agent 新范式:FastGPT+MCP 协议实现工具增强型智能体构建
  • VSCode Copilot 登录异常排查与修复指南
  • 飞书 OpenClaw 接入指南:无需服务器通过长连接运行机器人
  • Superpowers 编码 Agent 技能框架使用与原理分析
  • OpenClaw 配置与 QQ 机器人接入指南
  • C++26 反射驱动类型检查重塑代码质量
  • Docker Registry 私有仓库搭建实战 (v1/v2 详解)

相关免费在线工具

  • 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