尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Spring AI 实战:从入门到项目落地

Spring AI 实战:从入门到项目落地 1. 引言Spring AI 是 Spring 官方推出的 AI 应用开发框架旨在为 Java 开发者提供一套统一、简洁的 API用于对接 OpenAI、Azure OpenAI、Hugging Face、Ollama 等主流大语言模型。它借鉴了 Spring 生态一贯的「约定优于配置」理念让开发者可以用熟悉的依赖注入、自动配置和模板模式快速构建 AI 应用。本文将从环境搭建开始逐步讲解 Spring AI 的核心概念、常用 API并通过多个可运行的实战案例带你完成从「Hello World」到「RAG 知识库问答」的完整落地。2. 环境准备2.1 技术栈要求JDK17 及以上推荐 21构建工具Maven 3.8 或 Gradle 7.5Spring Boot3.2.x 及以上Spring AI1.0.0-M6 及以上本文以 1.0.0-M6 为例模型服务OpenAI API Key或本地 Ollama 部署的开源模型2.2 创建项目推荐使用 Spring Initializr 创建项目选择 Spring Boot 3.2.x并添加以下依赖dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version1.0.0-M6/version /dependency如果使用 Maven还需要在pom.xml中配置 Spring AI 的里程碑仓库repositories repository idspring-milestones/id nameSpring Milestones/name urlhttps://repo.spring.io/milestone/url snapshots enabledfalse/enabled /snapshots /repository /repositories2.3 配置 API Key在application.yml中配置 OpenAI 的 API Key 和基础地址spring: ai: openai: api-key: ${OPENAI_API_KEY} base-url: https://api.openai.com chat: options: model: gpt-4o-mini temperature: 0.7如果使用本地 Ollama则配置如下spring: ai: ollama: base-url: http://localhost:11434 chat: options: model: qwen2.5:7b3. 第一个 AI 应用ChatClient 入门3.1 核心概念Spring AI 的核心抽象是ChatClient它提供了流式FluentAPI用于构建和发送聊天请求。与传统的RestTemplate风格不同ChatClient支持链式调用代码可读性更强。3.2 编写 Controller下面创建一个简单的 REST 接口接收用户问题并返回 AI 回答import org.springframework.ai.chat.client.ChatClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder builder) { this.chatClient builder.build(); } GetMapping(/chat) public String chat(RequestParam String message) { return chatClient.prompt() .user(message) .call() .content(); } }3.3 测试接口启动应用后访问以下地址即可测试curl http://localhost:8080/chat?message用一句话介绍Spring%20AI返回结果示例Spring AI 是 Spring 官方推出的 AI 应用开发框架帮助 Java 开发者以统一、简洁的方式集成大语言模型能力。4. 流式输出打字机效果在实际业务中流式输出能显著提升用户体验。Spring AI 通过Flux支持响应式流式返回import org.springframework.ai.chat.client.ChatClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; RestController public class StreamChatController { private final ChatClient chatClient; public StreamChatController(ChatClient.Builder builder) { this.chatClient builder.build(); } GetMapping(/chat/stream) public FluxString streamChat(RequestParam String message) { return chatClient.prompt() .user(message) .stream() .content(); } }前端可以使用fetch配合ReadableStream实现打字机效果也可以直接使用 SSEServer-Sent Events协议接收数据。5. 结构化输出让 AI 返回 JSON5.1 定义实体类很多时候我们需要 AI 返回结构化数据而不是纯文本。Spring AI 提供了BeanOutputConverter来实现这一需求。首先定义一个实体类public record BookInfo(String title, String author, int year, String summary) {}5.2 使用 BeanOutputConverterimport org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.converter.BeanOutputConverter; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; RestController public class StructuredOutputController { private final ChatClient chatClient; public StructuredOutputController(ChatClient.Builder builder) { this.chatClient builder.build(); } GetMapping(/book) public BookInfo getBookInfo(RequestParam String name) { BeanOutputConverterBookInfo converter new BeanOutputConverter(BookInfo.class); String json chatClient.prompt() .user(请介绍书籍《 name 》的信息包括书名、作者、出版年份和内容简介。 converter.getFormat()) .call() .content(); return converter.convert(json); } }这里的关键是converter.getFormat()会在提示词中追加 JSON Schema 约束引导模型输出符合实体类结构的 JSON再由converter.convert()完成反序列化。6. 提示词模板复用 Prompt在实际项目中提示词往往需要动态拼接。Spring AI 提供了PromptTemplate支持占位符替换import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.prompt.PromptTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Map; RestController public class PromptTemplateController { private final ChatClient chatClient; public PromptTemplateController(ChatClient.Builder builder) { this.chatClient builder.build(); } GetMapping(/translate) public String translate(RequestParam String text, RequestParam String targetLang) { PromptTemplate template new PromptTemplate( 你是一位专业翻译。请将以下内容翻译成{targetLang}只输出翻译结果\n{text}); return chatClient.prompt(template.create(Map.of( text, text, targetLang, targetLang ))).call().content(); } }7. 实战案例RAG 知识库问答7.1 什么是 RAGRAGRetrieval-Augmented Generation检索增强生成是一种将外部知识库与大语言模型结合的技术。它先根据用户问题检索相关文档片段再将这些片段作为上下文注入提示词让模型基于真实资料回答从而减少幻觉、提升准确性。7.2 添加向量数据库依赖本文使用 Redis 作为向量数据库需要添加以下依赖dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-redis-store-spring-boot-starter/artifactId version1.0.0-M6/version /dependency7.3 配置向量数据库spring: data: redis: host: localhost port: 6379 ai: openai: api-key: ${OPENAI_API_KEY} embedding: options: model: text-embedding-3-small7.4 文档加载与向量化import org.springframework.ai.document.Document; import org.springframework.ai.reader.TextReader; import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import java.util.List; Service public class KnowledgeBaseService { private final VectorStore vectorStore; private final ResourceLoader resourceLoader; public KnowledgeBaseService(VectorStore vectorStore, ResourceLoader resourceLoader) { this.vectorStore vectorStore; this.resourceLoader resourceLoader; } public void loadDocument(String resourcePath) { Resource resource resourceLoader.getResource(resourcePath); // 1. 读取文档 TextReader reader new TextReader(resource); ListDocument documents reader.get(); // 2. 切分文档 TokenTextSplitter splitter new TokenTextSplitter(); ListDocument chunks splitter.apply(documents); // 3. 向量化并存储 vectorStore.add(chunks); } }7.5 实现问答接口import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.document.Document; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.stream.Collectors; RestController public class RagController { private final ChatClient chatClient; private final VectorStore vectorStore; public RagController(ChatClient.Builder builder, VectorStore vectorStore) { this.chatClient builder.build(); this.vectorStore vectorStore; } GetMapping(/rag) public String ask(RequestParam String question) { // 1. 检索相关文档 ListDocument documents vectorStore.similaritySearch( SearchRequest.query(question).withTopK(3)); // 2. 拼接上下文 String context documents.stream() .map(Document::getText) .collect(Collectors.joining(\n\n)); // 3. 构造提示词并调用模型 return chatClient.prompt() .user(请基于以下资料回答问题。如果资料中没有相关信息请如实说明。\n\n 资料\n context \n\n问题 question) .call() .content(); } }7.6 测试 RAG 流程首先加载知识库文档curl -X POST http://localhost:8080/kb/load?resourcePathclasspath:docs/spring-ai-guide.txt然后提问curl http://localhost:8080/rag?questionSpring%20AI支持哪些向量数据库8. 函数调用让 AI 执行工具8.1 定义工具方法函数调用Function Calling允许模型在回答过程中调用外部工具。下面实现一个查询天气的功能import org.springframework.ai.tool.annotation.Tool; import org.springframework.stereotype.Component; Component public class WeatherTools { Tool(description 根据城市名称查询当前天气) public String getWeather(String city) { // 实际项目中可调用第三方天气 API return 城市 city 天气晴温度26℃湿度45%; } }8.2 在 ChatClient 中注册工具import org.springframework.ai.chat.client.ChatClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; RestController public class FunctionCallingController { private final ChatClient chatClient; public FunctionCallingController(ChatClient.Builder builder, WeatherTools weatherTools) { this.chatClient builder .defaultTools(weatherTools) .build(); } GetMapping(/weather) public String askWeather(RequestParam String question) { return chatClient.prompt() .user(question) .call() .content(); } }当用户问「北京今天天气怎么样」时模型会自动调用getWeather(北京)方法并将返回结果组织成自然语言回答。9. 多模态图片理解Spring AI 还支持多模态输入。以下示例演示如何让模型理解图片内容import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.Media; import org.springframework.core.io.ClassPathResource; import org.springframework.util.MimeTypeUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; RestController public class VisionController { private final ChatClient chatClient; public VisionController(ChatClient.Builder builder) { this.chatClient builder.build(); } GetMapping(/vision) public String describeImage() { Media image new Media( MimeTypeUtils.IMAGE_PNG, new ClassPathResource(sample.png).getInputStream()); UserMessage message new UserMessage( 请描述这张图片的内容, List.of(image)); return chatClient.prompt(new Prompt(message)) .call() .content(); } }10. 生产实践与注意事项10.1 错误处理与重试调用外部模型服务时网络抖动、限流等问题不可避免。建议使用 Spring Retry 或 Resilience4j 增加重试和熔断机制import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; Service public class AiService { Retryable( retryFor {RuntimeException.class}, maxAttempts 3, backoff Backoff(delay 1000, multiplier 2)) public String callWithRetry(String prompt) { // 调用 ChatClient return chatClient.prompt().user(prompt).call().content(); } }10.2 成本控制Token 限制通过maxTokens限制单次输出长度。模型选择简单任务使用小模型如 gpt-4o-mini复杂任务才使用大模型。缓存对高频、结果稳定的请求做本地缓存。流式输出优先使用流式接口减少等待时间。10.3 安全与合规敏感信息过滤在发送请求前对用户输入做脱敏处理。输出审核对模型输出进行内容安全检测。API Key 管理使用环境变量或配置中心管理密钥切勿硬编码。日志脱敏避免在日志中记录完整的用户输入和模型输出。11. 总结本文从零开始系统讲解了 Spring AI 的核心用法环境搭建通过 Spring Initializr 快速创建项目并配置模型服务。基础对话使用ChatClient实现同步和流式问答。结构化输出通过BeanOutputConverter让 AI 返回 JSON。提示词模板使用PromptTemplate复用和管理提示词。RAG 实战结合向量数据库实现知识库问答。函数调用让模型自动调用外部工具。多模态支持图片理解等能力。Spring AI 仍在快速迭代中建议持续关注官方文档和 Release Notes。下一步可以尝试将 Spring AI 集成到你的业务系统中结合函数调用和 RAG 构建更智能的应用。
返回列表