Spring AI 是 Spring 官方团队在2023年推出的全新开源框架,专门用于在 Java 生态系统中集成人工智能能力。作为一个长期从事企业级应用开发的工程师,我亲历了从早期需要自行封装各种AI SDK到如今使用标准化框架的转变过程。Spring AI 的出现彻底改变了Java开发者使用AI模型的方式。
Spring AI 的核心设计理念是"统一抽象,简化集成"。它通过以下几方面实现这一目标:
实际开发中,这种设计使得切换AI模型提供商变得异常简单。例如从OpenAI切换到DeepSeek,通常只需修改配置文件的API地址和密钥,业务代码几乎无需改动。
Spring AI 目前支持的主要功能包括:
| 功能类型 | 实现能力 | 典型应用场景 |
|---|---|---|
| 聊天模型 | 文本生成、问答、代码生成等 | 智能客服、内容创作助手 |
| 嵌入模型 | 文本向量化 | 语义搜索、文档聚类 |
| 图像模型 | 图片生成与编辑 | 营销素材创作、产品设计 |
| 语音模型 | 语音识别与合成 | 语音助手、音频内容生成 |
| 向量数据库集成 | 与Pinecone等数据库的无缝对接 | RAG应用、知识库系统 |
Spring AI 目前处于快速迭代阶段,版本兼容性是需要特别注意的:
在实际项目中,我强烈建议使用Spring Boot 3.3.x + Spring AI 1.0.0-M7的组合,这是目前最稳定的搭配。对于生产环境,建议等待1.0.0正式版发布后再进行大规模应用。
Spring AI要求JDK 17或更高版本。推荐通过以下方式获取:
bash复制# 在~/.bashrc或~/.zshrc中添加
export JAVA_HOME=/path/to/jdk-17
export PATH=$JAVA_HOME/bin:$PATH
bash复制java -version
# 应输出类似:openjdk version "17.0.8" 2023-07-18
推荐使用以下开发工具:
个人经验:IntelliJ IDEA对Spring AI的自动补全和代码导航支持更好,特别是在处理ChatClient等流式API时。
最快捷的方式是通过start.spring.io生成项目骨架:
对于已有项目或需要更精细控制的情况,可手动配置pom.xml:
xml复制<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
</parent>
<properties>
<spring-ai.version>1.0.0-M7</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- 可选:用于流式响应 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
不推荐的做法:
推荐的安全实践:
bash复制# Linux/macOS
export DEEPSEEK_API_KEY=your_api_key_here
# Windows
set DEEPSEEK_API_KEY=your_api_key_here
yaml复制spring:
ai:
openai:
api-key: ${DEEPSEEK_API_KEY}
yaml复制spring:
ai:
openai:
api-key: ${DEEPSEEK_API_KEY}
base-url: https://api.deepseek.com/v1
chat:
options:
model: deepseek-chat
temperature: 0.7
max-tokens: 2000
embedding:
enabled: false
server:
port: 8080
关键参数说明:
在实际项目中,我通常采用profile区分环境配置:
yaml复制# application-dev.yml
spring:
ai:
openai:
api-key: dev_key
chat.options.temperature: 0.9 # 开发环境更高创造性
# application-prod.yml
spring:
ai:
openai:
api-key: ${PROD_API_KEY}
chat.options.temperature: 0.5 # 生产环境更保守
通过spring.profiles.active=dev激活不同配置。
java复制@RestController
@RequestMapping("/api/chat")
public class ChatController {
private final OpenAiChatModel chatModel;
public ChatController(OpenAiChatModel chatModel) {
this.chatModel = chatModel;
}
@GetMapping("/sync")
public ResponseEntity<Map<String, String>> chatSync(
@RequestParam String message) {
long start = System.currentTimeMillis();
String response = chatModel.call(message);
long duration = System.currentTimeMillis() - start;
return ResponseEntity.ok(Map.of(
"response", response,
"tokens", String.valueOf(response.length() / 4), // 近似估算
"duration", duration + "ms"
));
}
}
对于需要实时显示的场景,流式响应能显著提升用户体验:
java复制@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String message) {
Prompt prompt = new Prompt(message);
return chatModel.stream(prompt)
.map(ChatResponse::getResults)
.flatMapIterable(list -> list)
.map(result -> result.getOutput().getContent())
.doOnSubscribe(sub -> log.info("开始流式处理: {}", message))
.doOnComplete(() -> log.info("流式处理完成"));
}
踩坑提醒:流式响应需要客户端支持Server-Sent Events (SSE)。前端可以使用EventSource API或专门的SSE库来处理响应。
Spring AI推荐的更高级抽象是ChatClient,它提供了更流畅的API:
java复制@RestController
@RequiredArgsConstructor
public class AdvancedChatController {
private final ChatClient chatClient;
@GetMapping("/adv")
public String advancedChat(@RequestParam String query) {
return chatClient.prompt()
.system("你是一个专业的Java技术专家")
.user(u -> u.text(query)
.param("currentDate", LocalDate.now()))
.call()
.content();
}
@GetMapping("/adv/stream")
public Flux<String> advancedStream(@RequestParam String query) {
return chatClient.prompt()
.system(s -> s.text("你是一个AI助手")
.param("style", "幽默风趣"))
.user(query)
.stream()
.content();
}
}
ChatClient的主要优势:
在实际生产环境中,网络波动和API限制是常见问题。以下是增强健壮性的实践:
java复制@Configuration
public class AIConfig {
@Bean
public RetryTemplate aiRetryTemplate() {
return RetryTemplate.builder()
.maxAttempts(3)
.exponentialBackoff(1000, 2, 5000)
.retryOn(OpenAiApiException.class)
.build();
}
@Bean
public ChatClient robustChatClient(
ChatClient.Builder builder,
RetryTemplate retryTemplate) {
return builder.defaultSystem("你是一个AI助手")
.defaultOptions(options -> options
.withTemperature(0.7f)
.withMaxTokens(1000))
.withRetryTemplate(retryTemplate)
.build();
}
}
这种配置实现了:
对于高并发场景,需要优化HTTP连接池:
yaml复制spring:
ai:
openai:
client:
connect-timeout: 5s
read-timeout: 30s
max-connections: 100
max-per-route: 50
对相对静态的查询结果实施缓存:
java复制@Cacheable("aiResponses")
public String getCachedResponse(String query) {
return chatClient.prompt()
.user(query)
.call()
.content();
}
配合Spring Cache使用Redis等缓存后端。
java复制@Configuration
public class AIMetricsConfig {
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags(
"application", "spring-ai-demo");
}
@Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}
@Service
@RequiredArgsConstructor
public class AIService {
private final ChatClient chatClient;
@Timed(value = "ai.chat.time", description = "Time spent processing AI chat")
@Counted(value = "ai.chat.requests", description = "Total AI chat requests")
public String processQuery(String query) {
return chatClient.prompt()
.user(query)
.call()
.content();
}
}
这样可以在Prometheus+Grafana中监控:
java复制@GetMapping("/safe-chat")
public String safeChat(@RequestParam @Size(max=500) String message) {
// 自动验证消息长度不超过500字符
return chatClient.call(message);
}
java复制public String filterResponse(String rawResponse) {
// 移除可能的敏感信息
return rawResponse.replaceAll("(?i)password|token|secret", "***");
}
java复制@SpringBootTest
class ChatServiceTest {
@MockBean
private OpenAiChatModel chatModel;
@Autowired
private ChatService chatService;
@Test
void testChatResponse() {
when(chatModel.call(anyString()))
.thenReturn("Mocked AI response");
String result = chatService.chat("Hello");
assertEquals("Mocked AI response", result);
}
}
java复制@TestConfiguration
public class TestAIConfig {
@Bean
@Primary
public OpenAiChatModel testChatModel() {
return new OpenAiChatModel(new OpenAiApi("http://localhost:8888"),
OpenAiChatOptions.builder()
.withModel("test-model")
.build());
}
}
配合WireMock模拟AI API响应。
问题1:启动时报No qualifying bean of type 'OpenAiChatModel'
可能原因:
解决方案:
spring.ai.openai.api-key配置spring-ai-openai-spring-boot-starter依赖问题2:流式接口返回完整内容而非流式
可能原因:
解决方案:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
问题3:响应速度慢
优化建议:
yaml复制spring:
ai:
openai:
client:
read-timeout: 30s
问题4:遇到429 Too Many Requests
解决方案:
java复制@Bean
public RateLimiter aiRateLimiter() {
return RateLimiter.create(5); // 5请求/秒
}
问题5:响应不符合预期
调试步骤:
问题6:中文响应质量差
优化方案:
java复制.system("你是一个中文AI助手,请始终使用简体中文回答")
code复制com.example.ai
├── config # 配置类
├── controller # Web层
├── service # 业务逻辑
├── client # AI客户端封装
├── model # 领域对象
└── exception # 异常处理
避免在Controller中直接使用ChatClient:
java复制@Service
@RequiredArgsConstructor
public class AIChatService {
private final ChatClient chatClient;
public String generateTechnicalAnswer(String question) {
return chatClient.prompt()
.system("你是一个Java技术专家")
.user(question)
.call()
.content();
}
public Flux<String> streamCreativeWriting(String prompt) {
return chatClient.prompt()
.system("你是一个创意作家")
.user(prompt)
.stream()
.content();
}
}
实现自定义PromptTransformer:
java复制@Component
public class LoggingPromptTransformer implements PromptTransformer {
@Override
public Prompt transform(Prompt prompt) {
log.info("Processing prompt with messages: {}", prompt.getMessages());
return prompt;
}
}
自动会被Spring AI探测并应用。
java复制@Bean
public ChatClient functionCallingChatClient(ChatClient.Builder builder) {
return builder.defaultFunctions("weatherFunction")
.build();
}
@Function(name = "weatherFunction")
public String weatherFunction(@Description("城市名称") String location) {
return "当前" + location + "天气:晴朗,25℃";
}
(待Spring AI正式支持后补充实现)
配置示例(以Pinecone为例):
yaml复制spring:
ai:
vectorstore:
pinecone:
api-key: ${PINECONE_API_KEY}
environment: gcp-starter
index-name: tech-docs
project-name: my-project
使用示例:
java复制@Autowired
private VectorStore vectorStore;
public void storeDocument(String text) {
vectorStore.add(List.of(
new Document(text, Map.of("source", "web"))
));
}
public List<Document> search(String query) {
return vectorStore.similaritySearch(query);
}
根据Spring AI的roadmap,未来版本将带来:
对于现有项目,建议:
在实际项目中使用Spring AI的过程中,最大的体会是它显著降低了AI集成门槛,但同时也需要注意不要过度依赖特定提供商的API特性。良好的分层设计能让应用在AI技术快速演进中保持灵活性。