Spring AI与Ollama集成实战:构建智能文本处理微服务

Spring AI与Ollama集成实战:构建智能文本处理微服务 在实际工程和开发场景中“Making”这个词往往被用来指代从零开始构建、组装或实现某个功能、系统或产品的全过程。它不仅仅是写代码还包括需求理解、技术选型、环境搭建、模块设计、编码实现、测试验证、部署上线以及后续的维护优化。对于开发者而言能否高效、可靠地完成一个“Making”过程直接决定了项目的质量和交付效率。当前人工智能AI技术正深度融入软件开发的各个环节从代码生成、测试到系统设计AI 辅助工具和框架如 Spring AI、各类 AI Agent、AI 编程插件正在改变传统的“Making”模式。然而工具本身并不能替代对底层原理、工程规范和问题排查能力的掌握。本文将围绕一个典型的“Making”流程展示如何在一个具体的技术场景例如构建一个具备 AI 能力的微服务端点中系统性地应用工程实践并重点阐述在集成 AI 组件时需要注意的关键细节、常见陷阱及排查方法。目标是让读者不仅能按步骤完成一个可运行的原型更能理解每一步背后的设计考量具备独立解决实际问题的能力。1. 明确目标与技术选型我们要“Make”什么在开始任何动手操作之前必须清晰地定义项目目标。模糊的需求是项目失败的主要根源之一。1.1 定义项目范围假设我们要构建一个简单的文本处理微服务它提供一个 REST API 接口。用户向该接口发送一段文本服务端调用一个 AI 模型例如用于文本摘要或情感分析进行处理并将结果返回给用户。这个目标看似简单但已经包含了 Web 服务搭建、AI 模型集成、API 设计等多个核心环节。1.2 技术栈选型及理由技术选型需要权衡学习成本、社区生态、性能要求和团队技术储备。Web 框架Spring Boot理由Java 生态中事实上的标准提供快速启动、自动配置和丰富的 Starter 依赖能极大简化 Web 服务的开发。与 Spring AI 等项目无缝集成。AI 模型集成Spring AI理由Spring 官方项目旨在简化 AI 功能在 Spring 应用中的集成。它提供了对多种 AI 模型提供商如 OpenAI, Azure OpenAI, Ollama 本地模型的抽象允许通过更换配置而非代码来切换模型符合 Spring 的编程习惯。项目管理与构建Maven理由在 Java 生态中广泛使用依赖管理清晰。本地 AI 模型可选Ollama理由对于不想依赖外部 API 或需要离线运行的场景Ollama 可以方便地在本地部署和运行大型语言模型LLMSpring AI 也提供了对它的支持。选型对比表组件选项一选项二本次选择理由Web 框架Spring BootQuarkus / Micronaut生态更成熟与 Spring AI 集成度最高AI 集成Spring AI直接调用 OpenAI SDK抽象程度高便于切换模型符合 Spring 风格构建工具MavenGradle受众更广配置文件结构简单明了本地模型Ollama直接使用 Hugging Face Transformers部署和使用更简单适合快速原型验证基于以上选型我们的项目雏形是一个基于 Spring Boot Spring AI 的 RESTful 服务可能使用 Ollama 提供的本地模型或云上的 AI 服务。2. 环境准备与项目初始化“工欲善其事必先利其器”。一个稳定、一致的开发环境是后续所有工作的基础。2.1 基础环境配置Java Development Kit (JDK)推荐使用 JDK 17 或 21LTS 版本。检查安装java -versionMaven确保 Maven 已安装并可用的。mvn -versionIDE集成开发环境IntelliJ IDEA推荐或 Eclipse。确保已安装并配置好 Maven 和 JDK。Ollama可选用于本地模型访问 Ollama 官网下载并安装。安装完成后拉取一个轻量级模型例如llama3.1:8bollama pull llama3.1:8b启动模型服务ollama run llama3.1:8b服务默认运行在http://localhost:11434。保持此终端运行。2.2 创建 Spring Boot 项目使用 Spring Initializr 快速生成项目骨架。访问 start.spring.io 。选择Project:MavenLanguage:JavaSpring Boot:选择最新的稳定版如 3.3.0Project Metadata:Group:com.exampleArtifact:ai-text-servicePackaging:JarJava:17 或 21Dependencies:添加Spring Web和Spring AI。注意在 Initializr 上可能无法直接找到Spring AI因为它相对较新。如果找不到可以手动在生成的pom.xml中添加依赖。点击 “Generate” 下载项目压缩包并解压到工作目录。2.3 检查与调整 Maven 依赖解压后用 IDE 打开项目。检查pom.xml文件。由于 Spring AI 可能不在 Initializr 默认列表中我们需要手动添加。完整的pom.xml关键部分示例?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.3.0/version relativePath/ /parent groupIdcom.example/groupId artifactIdai-text-service/artifactId version0.0.1-SNAPSHOT/version nameai-text-service/name descriptionDemo project for Spring AI integration/description properties java.version17/java.version spring-ai.version1.0.0-M3/spring-ai.version !-- 使用当时最新的稳定版本 -- /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI Starter -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency !-- 使用 Ollama 提供商 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-ollama-spring-boot-starter/artifactId /dependency !-- 测试依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin /plugins /build /project关键解释spring-ai.version必须明确指定且需要与你的 Spring Boot 版本兼容。请查阅 Spring AI 官方文档获取版本映射关系。spring-ai-bom引入 BOMBill of Materials来统一管理所有 Spring AI 相关依赖的版本避免冲突。spring-ai-ollama-spring-boot-starter这是为 Ollama 定制的 Starter它会自动配置与本地 Ollama 服务通信所需的客户端。3. 核心代码实现构建 AI 文本处理服务项目骨架搭建好后开始编写业务逻辑。我们将遵循 Controller-Service 的经典分层模式。3.1 配置 AI 模型连接首先需要在src/main/resources/application.properties中配置 Spring AI 如何连接到我们的模型以 Ollama 为例。# 应用服务器端口 server.port8080 # Spring AI Ollama 配置 spring.ai.ollama.base-urlhttp://localhost:11434 # Ollama 服务地址 spring.ai.ollama.chat.modelllama3.1:8b # 指定要使用的模型名称必须与 Ollama 拉取的模型一致重要如果使用 OpenAI 等云服务则需要配置 API Key 和 Base URL格式类似spring.ai.openai.api-keyyour-key。Spring AI 的配置属性因提供商而异。3.2 定义 API 请求和响应模型创建简单的 Java 类来表示 API 的输入和输出。这有助于保持代码的清晰度和类型安全。src/main/java/com/example/aitextservice/model/AiRequest.javapackage com.example.aitextservice.model; public class AiRequest { private String message; // 默认构造函数为 JSON 反序列化所必需 public AiRequest() { } public AiRequest(String message) { this.message message; } // Getter 和 Setter public String getMessage() { return message; } public void setMessage(String message) { this.message message; } }src/main/java/com/example/aitextservice/model/AiResponse.javapackage com.example.aitextservice.model; public class AiResponse { private String result; public AiResponse() { } public AiResponse(String result) { this.result result; } public String getResult() { return result; } public void setResult(String result) { this.result result; } }3.3 创建 AI 服务层服务层负责封装与 AI 模型交互的复杂逻辑。这里我们将注入 Spring AI 提供的ChatClient。src/main/java/com/example/aitextservice/service/AiTextService.javapackage com.example.aitextservice.service; import org.springframework.ai.chat.client.ChatClient; import org.springframework.stereotype.Service; Service public class AiTextService { private final ChatClient chatClient; // 通过构造函数注入 ChatClient public AiTextService(ChatClient chatClient) { this.chatClient chatClient; } public String processText(String userMessage) { // 使用 ChatClient 发起对话请求 String aiResponse chatClient.prompt() .user(userMessage) .call() .content(); return aiResponse; } }代码解释Service标记这是一个 Spring 管理的服务类 Bean。ChatClient这是 Spring AI 的核心接口提供了流式和非流式两种方式与 AI 模型交互。这里使用简单的非流式调用。chatClient.prompt().user(...).call().content()这是一个流畅的 API 调用链。prompt()开始构建提示。user(userMessage)设置用户输入的消息。call()执行调用返回一个Response对象。content()从响应中提取 AI 生成的文本内容。3.4 创建 REST 控制器控制器层接收 HTTP 请求调用服务层并返回 HTTP 响应。src/main/java/com/example/aitextservice/controller/TextController.javapackage com.example.aitextservice.controller; import com.example.aitextservice.model.AiRequest; import com.example.aitextservice.model.AiResponse; import com.example.aitextservice.service.AiTextService; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; RestController public class TextController { private final AiTextService aiTextService; public TextController(AiTextService aiTextService) { this.aiTextService aiTextService; } PostMapping(/api/process) public AiResponse processText(RequestBody AiRequest request) { String result aiTextService.processText(request.getMessage()); return new AiResponse(result); } }代码解释RestController组合了Controller和ResponseBody表示这个类的所有方法返回的数据直接写入 HTTP 响应体通常是 JSON。PostMapping(/api/process)将该方法映射到 HTTP POST 请求路径为/api/process。RequestBody AiRequest request将请求体中的 JSON 数据自动反序列化为AiRequest对象。控制器方法非常简单接收请求 - 调用服务 - 返回响应。这种清晰的分层有利于测试和维护。4. 运行验证与结果分析代码写完后的第一步不是直接上线而是在本地进行充分的验证。4.1 启动应用确保 Ollama 服务如果使用仍在运行 (ollama run llama3.1:8b)。在 IDE 中右键点击主应用类通常名为AiTextServiceApplication选择 “Run”。或在项目根目录下使用 Maven 命令mvn spring-boot:run观察控制台日志如果没有错误Spring Boot 应用应该成功启动在 8080 端口。4.2 测试 API 接口使用curl、Postman 或任何 HTTP 客户端工具进行测试。使用curl命令测试curl -X POST http://localhost:8080/api/process \ -H Content-Type: application/json \ -d {message: 请用一句话解释什么是人工智能}预期成功的响应{ result: 人工智能是计算机科学的一个分支旨在创造能够执行通常需要人类智能的任务的机器或软件。 }实际返回内容会因模型和随机性而略有不同4.3 验证关键检查点应用启动日志中无异常显示 “Started AiTextServiceApplication in X seconds”。依赖注入确保ChatClient和AiTextService被正确创建和注入没有BeanCreationException。API 可达性HTTP POST 请求返回 200 OK 状态码。业务逻辑正确性AI 返回了与输入问题相关的、连贯的文本内容。5. 常见问题排查踩坑记录在实际“Making”过程中几乎一定会遇到问题。以下是集成 Spring AI 和 Ollama 时常见的坑及其解决方案。5.1 连接与配置问题问题现象可能原因检查与解决步骤启动报错Connection refused1. Ollama 服务未启动。2.application.properties中的base-url配置错误。1. 检查 Ollama 进程是否运行 (ps aux启动报错Model llama3.1:8b not found1. 模型名称拼写错误。2. 模型未成功拉取到本地。1. 检查application.properties中的model名称确保与ollama list命令输出中的名称完全一致。2. 执行ollama pull llama3.1:8b重新拉取模型。调用 API 返回 500 错误日志显示Read timed outAI 模型生成响应时间过长超过默认 HTTP 超时时间。1.调整超时设置在application.properties中增加spring.ai.ollama.chat.options.timeout60s。2.优化提示词要求模型回复更简洁。5.2 依赖与版本问题问题现象可能原因检查与解决步骤Maven 构建失败无法解析spring-ai-*依赖1.spring-ai.version不正确或不存在。2. Maven 仓库如 Maven Central尚未同步该版本。1. 访问 Spring AI 官方文档 确认最新稳定版本号。2. 检查项目的pom.xml中spring-ai.version是否正确。3. 尝试使用mvn clean compile -U(-U强制更新快照依赖)。启动时报ClassNotFoundException或NoSuchMethodError依赖版本冲突特别是 Spring Boot 和 Spring AI 版本不兼容。1. 查阅 Spring AI 文档的版本兼容性矩阵。2. 使用mvn dependency:tree命令分析依赖树排除冲突的传递依赖。5.3 业务逻辑问题问题现象可能原因检查与解决步骤AI 回复内容不相关或质量差提示词User Message不够清晰或具体。1.优化提示词工程在AiTextService中构建更明确的指令。例如将userMessage修改为请作为一位技术专家用通俗易懂的语言解释以下概念 userMessage。2. 调整 AI 模型的参数如temperature控制随机性可通过ChatClient的选项设置。6. 从原型到生产最佳实践与扩展方向一个能在本地跑通的 Demo 离生产级应用还有很大距离。以下是在真实项目中必须考虑的事项。6.1 配置管理外置化问题将模型地址、API Key 等敏感信息硬编码在application.properties中是不安全的也无法适应不同环境开发、测试、生产。实践使用application-{profile}.properties或application.yml区分环境配置。将敏感信息放入环境变量或云平台的密钥管理服务如 AWS Secrets Manager, Kubernetes Secrets。示例在application-prod.properties中引用环境变量。spring.ai.ollama.base-url${OLLAMA_BASE_URL:http://localhost:11434} # 如果使用 OpenAI则 # spring.ai.openai.api-key${OPENAI_API_KEY}6.2 增强鲁棒性异常处理当前代码一旦 AI 服务不可用整个 API 会失败。应添加全局异常处理ControllerAdvice返回友好的错误信息而不是 500 状态码。熔断与降级使用 Resilience4j 或 Sentinel 等库当 AI 服务持续不可用时快速失败或返回预设的默认值避免雪崩效应。日志与监控添加详细的日志记录输入、输出、耗时并集成 Micrometer 将指标如请求量、延迟、错误率暴露给 Prometheus 和 Grafana 等监控系统。6.3 性能与成本优化缓存对于相同或相似的查询可以考虑将 AI 响应结果缓存起来使用 Redis 或 Caffeine在一定时间内直接返回缓存结果显著降低延迟和 AI API 调用成本。异步处理如果处理耗时很长可以考虑将请求放入消息队列如 RabbitMQ, Kafka立即返回一个“已接收”的响应然后由后台工作者异步处理并通过其他方式如 WebSocket通知客户端结果。6.4 扩展功能流式响应Streaming修改服务层和控制器支持 Server-Sent Events (SSE)让 AI 生成的内容可以像 ChatGPT 那样逐字返回提升用户体验。多模型路由根据请求的内容、复杂度或成本要求动态选择不同的 AI 模型如简单问题用便宜的小模型复杂问题用能力强的大模型。结构化输出利用 AI 模型的 Function Calling 或 JSON Mode 能力要求模型直接返回结构化的 JSON 数据便于程序后续处理。通过以上步骤我们完成了一个完整的“Making”周期从目标定义、技术选型、环境准备、代码实现、验证测试到问题排查和生产级优化思考。这个流程和其中蕴含的工程化思维可以复制到绝大多数软件开发项目中。真正的“Making”能力正是在这样一次次的实践、踩坑和总结中积累起来的。