在大模型(LLM)技术爆发的当下,开发者们迫切需要一套简洁、统一的方案,将不同厂商的LLM能力集成到自身应用中。Spring AI的出现,恰好填补了这一空白------它依托Spring生态的强大优势,为LLM集成提供了标准化的API、自动配置等核心能力,让开发者无需关注不同LLM的底层差异,就能快速实现智能问答、文本生成、图像理解等功能。
Spring AI 1.1作为其重要更新版本,进一步完善了对主流LLM的支持(如OpenAI、阿里云通义千问、百度文心一言等),优化了配置方式与性能表现。本文将从环境准备入手,手把手教你接入主流LLM,实现智能问答与文本生成核心功能,并拓展讲解提示词工程、多模型切换等实用技巧,助力你快速上手Spring AI 1.1开发。
一、Spring AI 1.1 核心特性速览
在正式实操前,我们先梳理下Spring AI 1.1的核心优势,明白它为何能成为LLM集成的首选方案:
-
统一API抽象:对不同LLM厂商(OpenAI、通义千问、文心一言等)的接口进行标准化封装,开发者无需修改核心业务代码,即可切换不同LLM模型,降低接入成本与迁移风险。
-
原生Spring生态集成:无缝兼容Spring Boot、Spring Cloud等生态组件,支持基于application.yml的配置驱动开发,符合Spring开发者的使用习惯。
-
丰富的功能支持:除基础的文本问答、生成外,还支持流式响应、提示词模板、函数调用(Function Call)、向量数据库集成(用于RAG场景)等高级特性。
-
简化的依赖管理:通过starter依赖即可快速引入对应LLM的集成能力,无需手动管理复杂的第三方SDK依赖。
-
完善的异常处理:提供统一的异常封装与处理机制,便于开发者排查API调用超时、鉴权失败等问题。
二、环境准备:快速搭建Spring AI 1.1项目
本节将以Spring Boot 3.2(Spring AI 1.1最低支持Spring Boot 3.0+)为基础,搭建项目骨架,引入核心依赖。
2.1 版本选型说明
-
JDK:17+(Spring Boot 3.x最低要求,也是Spring AI推荐版本)
-
Spring Boot:3.2.x
-
Spring AI:1.1.0(最新稳定版,可通过Spring Initializr自动引入)
2.2 项目初始化(两种方式)
推荐使用Spring Initializr快速生成项目,也可手动配置pom.xml。
方式1:Spring Initializr生成(推荐)
-
访问Spring Initializr官网:https://start.spring.io/
-
配置基础信息:
Project:Maven/Gradle(本文以Maven为例)
-
Language:Java
-
Spring Boot:3.2.x
-
Group/Artifact:自定义(如com.example/spring-ai-demo)
-
Dependencies:搜索并添加「Spring AI Starter」(会自动引入spring-ai-core核心依赖),若需接入特定LLM(如OpenAI),可直接搜索「Spring AI Starter for OpenAI」。
-
点击「Generate」下载项目压缩包,解压后导入IDE(如IntelliJ IDEA)。
方式2:手动配置pom.xml
若需手动配置,在Spring Boot项目的pom.xml中添加Spring AI的依赖管理与核心依赖:
xml
<!-- Spring AI 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 核心依赖:Spring AI Core -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI 核心包 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
</dependency>
<!-- 示例:OpenAI 集成依赖(需接入其他LLM可替换为对应starter) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
三、核心实操:接入主流LLM,实现智能问答与文本生成
本节将以「OpenAI」「阿里云通义千问」为例,讲解如何通过Spring AI 1.1快速接入,分别实现智能问答(如知识库查询、问题解答)与文本生成(如文案创作、代码生成)功能。核心思路是:通过配置文件指定LLM的API密钥、模型名称等信息,Spring AI会自动创建对应的客户端实例,开发者直接注入使用即可。
3.1 接入OpenAI:基础示例(智能问答+文本生成)
OpenAI的GPT系列模型(如gpt-3.5-turbo、gpt-4)是目前最常用的LLM之一,Spring AI 1.1通过spring-ai-openai-spring-boot-starter提供了完善的支持。
步骤1:配置OpenAI相关信息
在application.yml中添加以下配置(需替换为自己的OpenAI API密钥,可从OpenAI官网获取):
yaml
spring:
ai:
openai:
api-key: sk-your-openai-api-key # 替换为你的OpenAI API密钥
chat:
model: gpt-3.5-turbo # 默认使用的聊天模型
temperature: 0.7 # 生成文本的随机性(0-2,值越大越随机)
max-tokens: 2048 # 生成文本的最大token数
步骤2:核心业务代码实现
Spring AI 1.1提供了ChatClient接口,用于与LLM进行聊天交互(支持问答、文本生成等场景)。我们只需通过@Autowired注入ChatClient实例,调用其generate方法即可完成请求。
(1)创建服务层(Service)
封装智能问答与文本生成的核心逻辑:
java
package com.example.springaidemo.service;
import org.springframework.ai.chat.ChatClient;
import org.springframework.stereotype.Service;
/**
* LLM核心服务:封装智能问答与文本生成功能
*/
@Service
public class LlmService {
// 注入Spring AI自动配置的ChatClient(OpenAI实现)
private final ChatClient chatClient;
// 构造器注入(Spring 4.3+支持,无需@Autowired)
public LlmService(ChatClient chatClient) {
this.chatClient = chatClient;
}
/**
* 智能问答:回答用户的问题
* @param question 用户问题(如"Spring AI是什么?")
* @return LLM的回答结果
*/
public String smartQa(String question) {
// 构建提示词(可根据需求优化提示词)
String prompt = String.format("请用通俗易懂的语言回答以下问题:%s", question);
// 调用ChatClient生成回答
return chatClient.generate(prompt);
}
/**
* 文本生成:根据需求生成指定类型的文本
* @param requirement 生成需求(如"写一篇关于Spring Boot的技术博客引言")
* @return 生成的文本内容
*/
public String textGeneration(String requirement) {
String prompt = String.format("请严格按照以下需求生成文本:%s。要求语言流畅、逻辑清晰,符合技术文章风格。", requirement);
return chatClient.generate(prompt);
}
/**
* 高级用法:带提示词模板的文本生成(更灵活的需求控制)
* @param topic 博客主题
* @param audience 目标读者(如"初学者"、"资深开发者")
* @return 生成的博客引言
*/
public String generateBlogIntro(String topic, String audience) {
// 提示词模板:通过占位符动态填充参数,提升复用性
String promptTemplate = "请为主题《%s》写一篇技术博客的引言,目标读者是%s。要求:1. 开篇点题,说明主题的重要性;2. 语言简洁,避免冗余;3. 引导读者继续阅读下文。";
String prompt = String.format(promptTemplate, topic, audience);
return chatClient.generate(prompt);
}
}
(2)创建控制层(Controller)
提供HTTP接口,供前端或其他服务调用:
java
package com.example.springaidemo.controller;
import com.example.springaidemo.service.LlmService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* LLM接口控制器:提供智能问答与文本生成的HTTP接口
*/
@RestController
@RequestMapping("/llm")
public class LlmController {
private final LlmService llmService;
public LlmController(LlmService llmService) {
this.llmService = llmService;
}
/**
* 智能问答接口
* @param question 用户问题
* @return 回答结果
*/
@GetMapping("/qa")
public String qa(@RequestParam String question) {
return llmService.smartQa(question);
}
/**
* 文本生成接口
* @param requirement 生成需求
* @return 生成的文本
*/
@GetMapping("/generate/text")
public String generateText(@RequestParam String requirement) {
return llmService.textGeneration(requirement);
}
/**
* 博客引言生成接口(带多参数)
* @param topic 博客主题
* @param audience 目标读者
* @return 博客引言
*/
@GetMapping("/generate/blog/intro")
public String generateBlogIntro(@RequestParam String topic, @RequestParam String audience) {
return llmService.generateBlogIntro(topic, audience);
}
}
步骤3:测试接口功能
启动Spring Boot应用,通过Postman或浏览器调用接口,测试功能是否正常:
-
智能问答测试:访问
http://localhost:8080/llm/qa?question=Spring AI是什么?,预期返回:"Spring AI是Spring生态下的一个AI集成框架,它为开发者提供了统一的API,用于快速接入各种大语言模型(如OpenAI、通义千问等),实现智能问答、文本生成等AI功能。它简化了LLM集成的复杂度,让开发者无需关注不同模型的底层差异,只需专注于业务逻辑开发..." -
文本生成测试:访问
http://localhost:8080/llm/generate/text?requirement=写一篇关于Spring Boot的技术博客引言,预期返回符合需求的博客引言内容。 -
博客引言生成测试:访问
http://localhost:8080/llm/generate/blog/intro?topic=Spring AI 1.1实战&audience=初学者,预期返回针对初学者的Spring AI 1.1实战博客引言。
3.2 切换到阿里云通义千问:无需修改核心代码
Spring AI 1.1的核心优势之一是「统一API抽象」,当我们需要从OpenAI切换到其他LLM(如阿里云通义千问)时,只需修改依赖与配置,核心业务代码(Service、Controller)完全无需改动。
步骤1:替换依赖(pom.xml)
移除OpenAI的starter依赖,添加通义千问的starter依赖:
xml
<!-- 移除OpenAI依赖(若之前添加) -->
<!--<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>-->
<!-- 添加通义千问依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-tongyi-spring-boot-starter</artifactId>
</dependency>
步骤2:配置通义千问信息
在application.yml中替换为通义千问的配置(需替换为自己的Access Key ID和Access Key Secret,可从阿里云控制台获取):
yaml
spring:
ai:
tongyi:
access-key-id: your-aliyun-access-key-id # 你的阿里云Access Key ID
access-key-secret: your-aliyun-access-key-secret # 你的阿里云Access Key Secret
chat:
model: qwen-turbo # 通义千问的聊天模型(qwen-turbo为基础版,qwen-plus为增强版)
temperature: 0.7
max-tokens: 2048
步骤3:直接测试接口
启动应用后,再次调用3.1中的所有接口(如/llm/qa、/llm/generate/text),会发现功能完全正常,只是底层调用的LLM从OpenAI切换到了通义千问。这就是Spring AI统一API的魅力------极大降低了多LLM接入与切换的成本。
四、实用拓展:提升LLM集成效果的关键技巧
除了基础的问答与文本生成,Spring AI 1.1还支持多种高级特性,掌握这些技巧能让你的AI应用更实用、更灵活。
4.1 提示词工程:优化生成结果的核心
LLM的生成效果很大程度上依赖于提示词(Prompt)的质量。Spring AI 1.1支持提示词模板(Prompt Template),可通过占位符动态填充参数,同时支持设置系统提示词(System Prompt)来定义LLM的角色。
示例:优化智能问答的提示词,让LLM以"技术顾问"的身份回答,且只回答与Java相关的问题:
java
/**
* 优化后的智能问答:限定LLM角色与回答范围
*/
public String optimizedSmartQa(String question) {
// 系统提示词:定义LLM的角色与规则
String systemPrompt = "你是一名资深Java技术顾问,只回答与Java相关的技术问题。若问题不涉及Java,直接回复'抱歉,我仅专注于Java相关技术问题的解答,请更换问题。'";
// 用户提示词:结合系统提示词与用户问题
String userPrompt = String.format("用户问题:%s", question);
// 构建完整提示词(系统提示词 + 用户提示词)
String fullPrompt = String.format("System: %s\nUser: %s", systemPrompt, userPrompt);
return chatClient.generate(fullPrompt);
}
测试:调用该方法时,若用户问题为"Java中如何实现线程安全?",LLM会以技术顾问的身份详细解答;若问题为"Python的列表推导式怎么用?",会返回预设的拒绝回答内容。
4.2 流式响应:提升用户体验
在生成较长文本(如万字博客、详细报告)时,若等待完整结果返回,用户体验会很差。Spring AI 1.1支持流式响应(Streaming Response),即LLM生成内容时逐句返回,前端可实时展示。
示例:实现流式文本生成(以OpenAI为例):
java
import org.springframework.ai.chat.ChatResponse;
import reactor.core.publisher.Flux;
/**
* 流式文本生成:逐句返回生成结果
* @param requirement 生成需求
* @return 流式响应(Flux)
*/
public Flux<String> streamingTextGeneration(String requirement) {
String prompt = String.format("请按照以下需求生成详细文本:%s", requirement);
// 调用stream方法获取流式响应(返回Flux<ChatResponse>)
Flux<ChatResponse> responseFlux = chatClient.stream(prompt);
// 提取每个响应中的生成文本,返回Flux<String>
return responseFlux.map(chatResponse -> chatResponse.getResult().getOutput().getContent());
}
控制器层接口调整(返回Flux):
java
/**
* 流式文本生成接口
*/
@GetMapping(value = "/generate/text/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamingGenerateText(@RequestParam String requirement) {
return llmService.streamingTextGeneration(requirement);
}
测试:调用该接口时,前端会实时接收LLM生成的内容并逐句展示,避免了长时间等待。
4.3 多模型动态切换:应对不同场景需求
实际开发中,可能需要根据不同场景(如成本、性能、功能)动态切换LLM模型。Spring AI 1.1支持通过ChatClientBuilder手动构建不同LLM的ChatClient实例,实现动态切换。
示例:手动构建OpenAI和通义千问的ChatClient,根据场景切换:
java
import org.springframework.ai.openai.OpenAiChatClient;
import org.springframework.ai.openai.OpenAiChatClientBuilder;
import org.springframework.ai.tongyi.TongYiChatClient;
import org.springframework.ai.tongyi.TongYiChatClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class DynamicLlmService {
// 从配置文件中读取各LLM的密钥
@Value("${spring.ai.openai.api-key:}")
private String openAiApiKey;
@Value("${spring.ai.tongyi.access-key-id:}")
private String tongYiAccessKeyId;
@Value("${spring.ai.tongyi.access-key-secret:}")
private String tongYiAccessKeySecret;
/**
* 动态获取ChatClient
* @param llmType LLM类型("openai"或"tongyi")
* @return 对应的ChatClient实例
*/
private ChatClient getChatClient(String llmType) {
return switch (llmType) {
case "openai" -> new OpenAiChatClientBuilder()
.apiKey(openAiApiKey)
.model("gpt-3.5-turbo")
.temperature(0.7)
.build();
case "tongyi" -> new TongYiChatClientBuilder()
.accessKeyId(tongYiAccessKeyId)
.accessKeySecret(tongYiAccessKeySecret)
.model("qwen-turbo")
.temperature(0.7)
.build();
default -> throw new IllegalArgumentException("不支持的LLM类型:" + llmType);
};
}
/**
* 动态切换LLM进行文本生成
* @param llmType LLM类型
* @param requirement 生成需求
* @return 生成结果
*/
public String dynamicTextGeneration(String llmType, String requirement) {
ChatClient chatClient = getChatClient(llmType);
return chatClient.generate(requirement);
}
}
测试:调用dynamicTextGeneration方法时,传入llmType="openai"则使用OpenAI,传入"tongyi"则使用通义千问,灵活应对不同场景。
五、常见问题排查
-
API密钥错误:表现为启动后调用接口报「401 Unauthorized」错误。解决方案:检查配置文件中的API密钥是否正确,确保密钥未过期,且具有对应模型的调用权限。
-
模型名称错误:表现为报「模型不存在」或「不支持该模型」错误。解决方案:确认使用的模型名称是否符合LLM厂商的规范(如OpenAI的gpt-3.5-turbo、通义千问的qwen-turbo)。
-
网络问题:调用OpenAI时若报超时错误,可能是国内网络无法访问。解决方案:配置代理,或切换为国内LLM(如通义千问、文心一言)。
-
依赖冲突:若项目中存在多个LLM的starter依赖,可能导致ChatClient自动配置失败。解决方案:根据当前使用的LLM,只保留对应的starter依赖。
六、总结
Spring AI 1.1通过统一的API抽象、原生的Spring生态集成,极大简化了主流LLM的接入流程。本文从环境搭建入手,通过完整的示例代码实现了OpenAI与通义千问的接入,讲解了智能问答与文本生成的核心功能,并拓展了提示词工程、流式响应、多模型动态切换等实用技巧,希望能帮助你快速上手Spring AI 1.1开发。
未来,Spring AI还将支持更多LLM厂商与高级特性(如多模态生成、RAG场景深度集成等)。如果你需要实现更复杂的AI功能(如基于知识库的问答、AI绘画等),可以进一步探索Spring AI的官方文档与示例项目。动手实践起来,让LLM能力快速赋能你的应用吧!