尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Spring AI 集成 Ollama:Java 本地大模型应用开发实战指南

Spring AI 集成 Ollama:Java 本地大模型应用开发实战指南 最近在把 AI 能力接进业务系统试了一圈之后我个人最推荐 Spring AI Ollama 这套本地大模型方案。Spring AI 是 Spring 官方出的 AI 框架把对大模型的调用抽象成一套统一的 Java API上层怎么接、底层换什么都由框架帮你挡掉Ollama 是一个极简的本地大模型运行器一条命令就能把 Qwen、Llama、DeepSeek 这类开源模型拉下来跑在你自己的电脑上。把这两者搭配起来你可以在不把数据送出去的前提下用熟悉的 Spring Boot 方式完成聊天问答、文档分析、文本总结这类功能。这篇内容是系列第 2 篇主要服务两类人一是刚接触大模型的 Java 开发者想尽快跑通一条可复现的完整链路二是想在内网低成本搭一套推理能力的技术负责人。本篇聚焦最核心的入门链路Ollama 安装、模型拉取、Spring AI 接通、消息返回再到高频问题排查。1. 项目整体思路为什么是 Spring AI Ollama1.1 这套组合到底解决了什么问题先说一个很现实的痛点。企业内部做 AI 功能最常见的卡点不是模型能力而是“数据能不能出去”。调云端大模型 API虽然效果不错但业务数据、用户隐私、日志内容全部要过一遍第三方服务这在很多公司是要走审批甚至直接不批的。所以本地部署大模型成了刚需特别是金融、政务、医疗、企业内部知识库这类场景。Ollama 解决了“模型怎么在本地跑起来”的问题。它把模型下载、量化、推理、内存管理全部封装好你不用懂 PyTorch、不用配 CUDA 环境装完就能跑。对于 Java 后端团队来说这个门槛直接降了一大截。Spring AI 解决了“Java 项目怎么优雅调用模型”的问题。如果没有 Spring AI你得自己拼 HTTP 请求自己处理流式输出、JSON 解析、错误重试而且每换一家模型厂商就要重写一遍接入层。Spring AI 从 Spring Cloud 那套设计思路里继承了很多优秀习惯把模型调用抽象成了 ChatClient、EmbeddingModel 这种接口你只需要注入一个 Bean业务代码里写几行就能完成一次对话。1.2 技术选型背后的关键考量我选这套组合之前其实也对比过其他方案。最原始的做法是直接写 RestTemplate 调 Ollama 的 /api/chat 接口代码量不大但问题在于一旦后面要接 OpenAI、要接云端 API或者要换嵌入式模型整个调用层全部要改。Spring AI 的抽象层把这个风险隔离掉了换模型提供商只改配置不改业务代码这是它最大的价值。另一个对比对象是 LangChain4j。它也很优秀但在 Spring 生态的契合度上Spring AI 明显更胜一筹因为它本身就是 Spring 官方出的和 Spring Boot、Spring Data、Spring Security 的集成都是亲儿子待遇。比如你可以在 AI 调用链路里直接用 Spring 的事务管理、缓存、配置中心这些 LangChain4j 虽然也能做但没有那么顺滑。选 Ollama 而不是直接用 llama.cpp 或者 vLLM理由也很简单Ollama 的模型管理能力太方便了。它内置了 Model 仓库机制支持 Tag 版本管理一条命令拉模型、一条命令删模型还能用 Modelfile 自定义模型的 system prompt 和参数模板。对于开发环境和个人电脑来说Ollama 就是最省心的运行器。1.3 整体方案架构整个链路其实很简单核心就三层第一层是模型层Ollama 负责在本地跑开源大模型默认监听http://localhost:11434。第二层是接入层Spring AI 的 Ollama Starter 封装了对 Ollama 的调用通过ChatClient暴露给上层。第三层是业务层你写正常的 Spring Service注入ChatClient调用chat()方法拿结果。所以整个项目搭起来只需要三步装 Ollama、拉模型、在 Spring Boot 里加依赖写代码。下面两个章节我会把每一步都拆开讲特别是那些不写进官方文档的坑。2. 动手前的环境准备与 Ollama 安装2.1 官网下载太慢国内镜像源直接安排Ollama 的官方下载地址在海外很多同学反馈下载速度感人几十 MB 的安装包能下半小时甚至直接超时失败。这个问题我实测最有效的方案是走国内镜像源。Windows 用户可以直接去国内镜像站下载安装包比如很多开源镜像站会同步 Ollama 的 Windows 安装包和 macOS 安装包。把OllamaSetup.exe下载下来后正常双击安装就行这个安装过程本身没有难度默认装到用户目录下。Linux 用户处理方式稍微不一样。官方给的安装脚本curl -fsSL https://ollama.com/install.sh | sh在国内大概率拉不动建议分两步走先去国内镜像源下载ollama-linux-amd64.tgz之类的二进制包手动解压安装。解压后把二进制放到/usr/local/bin把库文件放到/usr/local/lib然后创建 systemd service 或者直接用nohup ollama serve 后台启动。注意不要想着走系统代理或者改 hosts 去加速官方下载这个方向又慢又容易出问题。直接换成国内源是最稳的几分钟就能装完。另外再补一个细节macOS 用户如果有 Homebrew可以考虑brew install ollama这个命令本身也很快但国内 Homebrew 的源需要提前配好否则同样会遇到下载慢的问题。2.2 安装路径与模型存储位置调整Ollama 默认的模型存储路径很有迷惑性Windows 上默认会放在用户的.ollama/models目录里也就是 C 盘。很多人的 C 盘本来就不富裕一个大模型动辄 4GB、8GB几个模型下来 C 盘直接红了。解决办法是提前设置环境变量OLLAMA_MODELS把它指到你的 D 盘或者其他数据盘。比如我自己的配置是# Windows PowerShell 示例永久生效 setx OLLAMA_MODELS D:\ollama_models设置完之后务必重启 Ollama 进程否则改动不生效。可以从托盘图标退出 Ollama再重新打开或者直接把 Ollama 服务重启一遍。Linux 上同样可以在 systemd service 文件里加EnvironmentOLLAMA_MODELS/data/ollama来实现。另外还有一个环境变量值得一起配就是OLLAMA_HOST。默认 Ollama 只监听127.0.0.1:11434如果你要开给局域网里的其他机器访问需要设置OLLAMA_HOST0.0.0.0:11434。不过这个要谨慎局域网内开放意味着其他机器也能调你的模型如果是在公司内网建议确认网络策略允许。2.3 GPU 与 CPU 运行的基础配置Ollama 的一大优势就是自动检测 GPU有 NVIDIA 显卡的话装上对应版本的驱动和 CUDA runtime 后Ollama 会默认用 GPU 推理速度提升非常明显。但这里有个常见的坑AMD 显卡和核显用户。如果你的机器只有 AMD 核显比如很多办公电脑是 5600G、5700G 这种 APUOllama 的 GPU 支持可能不生效甚至因为尝试用 GPU 导致报错。这时候最简单的做法是强制 CPU 运行设置环境变量OLLAMA_NUM_GPU0让 Ollama 老老实实吃 CPU。我自己在 5600G 32G 内存的机器上实测过跑 7B 量化的 Qwen 模型CPU 推理大概每秒输出 3-5 个 token虽然不快但做开发测试、搭个内部问答机器人是够用的。如果你用的是AMD Ryzen AI 9 HX 370这种带 NPU 的新一代处理器Ollama 目前对 NPU 的支持还不算完善多数情况下还是走 CPU 或核显不用太纠结跑分先把链路跑通更重要。顺便说一句如果日志里出现了类似expected m1 and m2 to have the same dtype的报错十有八九是 GPU 和 CPU 混跑时的数据类型不一致问题。先按上面说的设OLLAMA_NUM_GPU0强制 CPU 跑看看能否恢复正常。这个我在后面的排查章节会详细说。2.4 首次拉取模型与命令行验证安装完成并调整好环境变量后先确认 Ollama 版本ollama --version能正常输出版本号就说明安装成功。接着拉取一个适合入门的模型我强烈推荐 Qwen 系列中文效果好社区活跃文档也全ollama run qwen2.5:7b这条命令会先把模型下载到本地然后自动进入一个交互式聊天界面。你在命令行里敲一句“你好”如果模型能正常回复就说明环境完全通了。这一步很重要一定要先确认命令行能通再往下做 Spring AI 集成否则你会分不清是模型问题还是 Java 代码问题。3. 模型管理与 Ollama 基础操作3.1 模型命名规则与常用命令当你进入 Ollama 的世界后会发现模型 Tag 有一套自己的命名规则。比如qwen2.5:7b和qwen2.5:7b-instruct-q4_K_M就是两个不同的 Tag。前者是官方推荐的默认版本后者是显式指定了量化等级的中间版本。实际上 Ollama 的模型名由模型名:标签组成标签不写时默认是latest但我不建议依赖 latest因为模型升级可能会导致行为变化让你的应用不可控。最好每次都显式指定 Tag。几个最常用的命令# 查看本地已经拉下来的模型 ollama list # 在命令行直接对话 ollama run qwen2.5:7b # 删除不再需要的模型释放磁盘空间 ollama rm qwen2.5:7b # 查看模型详细信息 ollama show qwen2.5:7bollama show除了能看参数规模、量化等级以外还会显示模型的上下文长度、参数配置等信息这对我们后面调 Spring AI 很有帮助。3.2 模型参数解读与上下文长度不少同学会问“如何查看本地大模型上下文长度”其实就是用上面提到的ollama show。看输出里的context_length字段或者看model_info里的context_length。默认情况下Ollama 为大多数模型设置的是 2048 或 4096 的上下文长度但 Qwen2.5 系列原生的最大上下文是 32K 甚至 128K也就是说默认配置远远没有发挥出模型的真实水平。如果在 Spring AI 里需要长文档处理就需要调大上下文。Ollama 这边可以通过 Modelfile 或者 API 参数来设置num_ctx。比如在 Spring AI 的配置里我们可以传一个options参数spring: ai: ollama: chat: options: num-ctx: 8192这个参数一定要记得根据自己的任务类型调整。短问答用默认 2048 没问题但你要丢一篇几千字的文档进去上下文不够的话模型会直接“失忆”忘记你之前给它的信息。3.3 通过 HTTP API 验证模型可用性在写 Java 代码之前建议先用 curl 直接调一次 Ollama 的接口确认 HTTP 层面没有问题。Ollama 默认提供两个接口一个是对话接口一个是原生生成接口。对话接口走的是 OpenAI 兼容风格长期看是主流我建议直接用这个curl http://localhost:11434/api/chat -d { model: qwen2.5:7b, messages: [ { role: user, content: 你好用一句话介绍你自己 } ] }正常的话会返回一个 JSON 数组里面包含了最终的回答内容。这一步验证通过后说明 Ollama 的 HTTP 服务没问题接下来就可以放心进入 Spring AI 的部分了。4. Spring AI 接入本地大模型实操4.1 创建项目与引入依赖Spring AI 目前对 Spring Boot 3.x 和 Java 17 支持最好建议直接用 start.spring.io 或者 IDE 内置的初始化器创建一个标准 Spring Boot 项目。然后在pom.xml里引入 Ollama 的 Starterdependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-ollama-spring-boot-starter/artifactId /dependency这里要特别注意版本对齐问题。Spring AI 的版本迭代比较快不同版本之间 API 会有调整最稳妥的做法是去 Spring AI 官网查当前 Release 对应的版本号然后在pom.xml的parent里指定或者通过dependencyManagement锁定版本。如果你使用的是比较新的 Spring Boot 3.2 和 Spring AI 1.0.0 之后的版本依赖坐标可能要写成spring-ai-starter-model-ollama。我推荐直接去 spring initializr 页面勾选 Ollama 依赖让脚手架帮你搞定版本这是最不容易出错的方法。4.2 核心配置项与参数解析Spring AI 接入 Ollama 的配置非常简洁核心就是 base-url、模型名和模型参数。一个最基础的配置如下spring: ai: ollama: base-url: http://localhost:11434 chat: model: qwen2.5:7b options: temperature: 0.7 num-predict: 512 top-p: 0.9 num-ctx: 8192参数逐个解释一下base-url是 Ollama 的地址默认就是 11434 端口如果你改了OLLAMA_HOST这里要对应改。model指定用哪个模型要和ollama list里看到的名字完全一致。temperature控制输出的随机性。值越低越确定适合做代码生成、信息抽取值越高越有创造性适合做文案创作。我建议服务端场景用 0.2-0.5 之间避免模型胡编。num-predict控制生成的最大 token 数量。512 对于一般问答够用了但如果你要模型输出长文章这里要调大。top-p是核采样参数默认 0.9 基本不用动。num-ctx就是前面提到的上下文长度根据你的任务调整。这里还有一个容易忽略的点如果你在多个环境里部署可以把这些配置放到 Spring Cloud Config 或者 Nacos 里通过配置文件动态切换模型真正做到“换模型不换代码”。4.3 对话调用与流式输出实现配置写好后在业务代码里注入ChatClient就能用了。先看最基础的同步调用Service public class ChatService { private final ChatClient chatClient; public ChatService(ChatClient chatClient) { this.chatClient chatClient; } public String ask(String question) { return chatClient.call(question); } }这段代码已经能完成一次完整的问答。但实际项目中我更推荐使用Prompt和ChatResponse的方式更方便加系统提示词和解析响应元数据public String askWithSystem(String question) { Prompt prompt new Prompt( question, OllamaOptions.builder() .withModel(qwen2.5:7b) .withTemperature(0.3f) .build() ); ChatResponse response chatClient.call(prompt); return response.getResult().getOutput().getText(); }如果你要做一个打字机效果的流式对话用Fluxpublic FluxString stream(String question) { return chatClient.stream(question); }前端通过 WebFlux 的 SSE 接口消费这个 Flux就能做到逐字输出的效果。这个体验在 Web 聊天页面里非常重要实测下来用 Ollama Spring AI 做流式基本没有额外延迟模型出多少字就能推多少字。注意如果你用的是 Spring MVC 而不是 WebFlux流式返回需要额外处理响应类型。最简单的方式是单独建一个RestController返回FluxString并引入spring-boot-starter-webflux依赖。4.4 结构化输出与 Function Calling 扩展聊完基本的文本问答我再分享两个我觉得很有价值的进阶能力。第一个是结构化输出。LLM 返回的是自然语言但业务系统往往需要 JSON。Spring AI 提供了OutputParser机制可以强制模型输出指定格式。比如想得到一个实体列表可以先定义 POJO然后让ChatClient帮你自动解析public record Person(String name, int age) {} ListPerson persons chatClient.call( new Prompt(从这段话中提取所有人的姓名和年龄张三25岁李四30岁), BeanOutputParser.list(Person.class) );原理是在请求里附加一段“请只输出 JSON 格式且符合以下 schema”的指令然后把模型的 JSON 响应反序列化成对象。这类能力很适合做信息抽取、报表生成。第二个是 Function Calling。Spring AI 允许你把自己的 Java 方法作为工具注册给模型。模型在回答问题时如果发现自己需要某个数据会主动调用你的方法。举个简单例子你有一个查询订单状态的方法模型在回答用户“我的订单现在什么状态”时会去调用这个方法拿数据再组织语言返回。这种模式能极大扩展模型能力解决模型“不知道实时数据”和“不会精确计算”的短板。注册方式很简单在一个Bean方法上定义函数Bean Description(查询订单物流状态) public FunctionOrderQueryRequest, String queryOrderStatus() { return request - orderService.getStatus(request.orderId()); }然后在 ChatClient 调用时通过withTools传入即可。这块功能比较深这篇不展开后续系列文章可以单独讲。5. 常见问题排查与性能优化5.1 下载慢、拉取失败类问题处理这类问题出现的频率最高。除了换国内镜像源之外还有几个细节值得关注。一是模型中断后重新下载。Ollama 支持断点续传中断后重新执行ollama run命令一般会接着下。如果发现没有续传可以试试先ollama pull再ollama runpull命令的进度条更直观。二是磁盘空间不足。模型下载前要确认磁盘剩余空间。ollama list里显示的是最终解压后的体积下载过程中还会有临时文件建议至少留出模型体积 1.5 倍的空间。我遇到过最尴尬的情况是下载到 90% 时磁盘满了然后模型文件损坏只能删掉重新拉。三是模型拉取成功但运行报错。这时候不要急着删先看完整报错日志。如果是量化格式不支持换个 Q4_K_M 这类常见量化版本基本能解决。5.2 模型加载失败与 dtype 异常前面提到的expected m1 and m2 to have the same dtype是 AMD 或集成显卡用户高频遇到的一个报错。这个报错本质上是模型的部分参数在 GPU 上加载部分参数在 CPU 上加载两者的数据类型没有对齐导致矩阵运算失败。最简单的处理方法就是前面说的在环境变量里设置OLLAMA_NUM_GPU0强制走 CPU然后重启 Ollama。如果你还是希望用 GPU 加速可以尝试更新显卡驱动或者换一个量化等级更高的模型比如用q4_K_M代替f16但这块兼容性因显卡型号而异不一定是 100% 能解决。另外还有一个常见的 dtype 问题是跨平台复制模型文件。比如你把别人电脑上的模型目录直接拷贝到自己机器上容易因为平台架构不同导致二进制文件不兼容。遇到这种情况老老实实重新 pull 一次别在模型文件上偷懒。5.3 Spring AI 连接失败与不输出 content这一节是 Java 侧最常踩的坑。先说连接失败如果 Spring AI 启动时报Connection refused: localhost/127.0.0.1:11434第一步先确认 Ollama 是否真的在运行。很多人启动 Ollama 后又把它退出了Spring Boot 起来当然连不上。第二步确认配置地址如果你设置了OLLAMA_HOST为非默认端口那么spring.ai.ollama.base-url要和它一致。第三步检查防火墙局域网访问的场景下防火墙可能会拦截 11434 端口。再有就是“模型返回正常但 Spring 调用拿不到 content”的问题。这个问题网上讨论热度很高尤其在对接 OpenAI 兼容服务时频繁出现。其实核心原因通常是两个一是响应 JSON 结构变化模型返回的数据里content字段的路径变了或者变成了空字符串二是num-predict设置得太小模型还没来得及输出完整答案就被截断导致content从模型侧看是 null。排查思路很简单先用 curl 原文看一下完整响应确认返回结构里有没有 text/content 字段。确认模型侧没问题后再把 Spring AI 的日志级别调到 DEBUG看一下它实际拿到的响应内容和解析路径。大多数能解。5.4 硬件配置参考与模型选型建议最后整理一份硬件参考表帮大家判断自己的机器能跑到什么程度。我平时测试的机器配置是CPU 为 AMD 5600G内存 32GB无独立显卡。这个配置属于“刚刚够用”的入门水平。模型规模量化等级建议内存是否建议在 32G 内存机器上运行速度体验7B / 8BQ4_K_M8-12GB可以推荐CPU 下 3-5 token/s可开发测试13B / 14BQ4_K_M16-24GB勉强可以但内存吃紧CPU 较慢建议有 GPU32BQ4_K_M32GB 以上不推荐CPU 基本不可用需要多卡 GPU如果是 N 卡且显存在 8GB 以上跑 7B/8B 或 14B 的量化模型都很流畅体验会好很多。最近很火的 Qwen2.5 系列本来就是多尺寸覆盖从 0.5B 到 72B 都有开发阶段可以先拉 0.5B 或 3B 的小模型验证代码确认链路通了再换大模型能省不少等待时间。还有一个小建议不要盲目追求模型尺寸。你在开发环境跑 7B 就好真要上线高并发再考虑部署到 GPU 服务器或迁移到云端 API。这套 Spring AI 抽象的好处就在这里切换模型只是改配置业务代码一行不用动。6. 项目生态与后续扩展6.1 与 Dify、ruoyi-ai 等开源项目对接现在社区里已经有很多项目直接把 Ollama 作为默认的模型后端了。比如 Dify你可以在模型供应商里选择 Ollama填上http://localhost:11434和模型名就能在可视化工作流里编排大模型应用。好处是 Dify 帮你做了知识库切片、Prompt 编排、日志审计而你只需要保证 Ollama 在后台正常运行。另一个典型项目是 ruoyi-ai 这类基于 Spring Boot 的管理系统脚手架它把 AI 能力集成到后台管理界面里底层同样可以对接 Ollama。通过 Spring AI 的抽象你不用关心底层到底是 Ollama 还是 OpenAI只管调ChatClient接口。我自己的经验是先在命令行把 Ollama 本身跑通再用 Spring AI 写最小示例最后放到业务系统里。这个顺序能帮你节约排查时间因为每一层的边界都很清晰。6.2 后续可以做的方向如果你已经顺利把 Spring AI Ollama 跑通下一步值得尝试的方向有接入 Embedding 模型做本地知识库问答把文档向量化后存储在向量数据库里实现基于本地文档的智能问答。使用spring-ai-rag模块做 Retrieval-Augmented Generation让模型引用你提供的私有资料来回答减少幻觉。把流式对话接入 WebSocket 或 SSE做一个真正可用的聊天机器人。在 Spring AI 中使用 Advisor 机制做日志记录、敏感信息过滤、多轮上下文记忆管理。这些都是同一个架构下的自然延伸底层模型和框架不变业务代码的可复用度很高。7. 实操心得与一个小技巧最后讲一点我个人的体会。这套方案最舒服的地方是“可控”。模型在本地参数调错了随时改上下文长度、量化等级、缓存机制都可以随手调整不像调云端 API 那样要考虑成本、限流和数据合规。对于个人开发者和中小团队来说用一个 7B 模型先把产品雏形跑起来等验证了需求、攒了用户量再逐步迁移到更大模型或 GPU 集群这是最务实的一条路。再分享一个小技巧很多人用 Ollama 时会遇到 Windows 控制台输出乱码的问题这跟模型本身没有关系是控制台代码页不对。把终端切到 UTF-8 编码chcp 65001再启动 Ollama或者直接用 Windows Terminal基本就正常了。最后提醒一句遇到问题先别急着改代码先用 curl 调一次 Ollama 的接口确认模型服务本身没问题再回头排查 Java 侧。这条排查顺序能帮你省掉一大半的纠结时间。如果你按这篇文章的顺序从安装走到 Spring AI 集成大概一小时内就能跑通祝你顺利。
返回列表