Spring AI是Spring生态系统中一个令人兴奋的新成员,它为Java开发者提供了与各种AI模型交互的统一接口。作为一个长期使用Spring框架的开发者,我发现Spring AI真正解决了我们在企业应用中整合AI功能时的痛点。
传统上,Java开发者想要接入OpenAI、Anthropic等AI服务,往往需要直接调用各家的REST API,处理各种低级别的HTTP请求和响应解析。而Spring AI通过提供高层抽象,让我们能够像使用Spring Data访问数据库那样自然地与AI模型交互。
注意:Spring AI目前仍处于快速迭代阶段(1.0.0-SNAPSHOT),API可能会有变动,建议在生产环境中谨慎使用。
Spring AI的设计哲学体现了Spring框架一贯的"约定优于配置"理念。它的核心价值体现在:
特别值得一提的是它的"检索增强生成"(RAG)支持,这让我们可以轻松实现基于自有知识库的问答系统,而不必完全依赖AI模型的通用知识。
根据官方文档,当前版本的Spring AI对运行环境有明确要求:
| 组件 | 最低版本 | 推荐版本 |
|---|---|---|
| Java | 17 | 17+ |
| Spring Boot | 3.2.0 | 3.3.0 |
| Maven | 3.6.3 | 3.9.6 |
我建议使用SDKMAN来管理Java版本:
bash复制sdk install java 17.0.11-tem
sdk use java 17.0.11-tem
使用Spring Initializr创建基础项目时,除了标准的Web依赖外,还需要添加Spring AI的BOM(物料清单)。这是我常用的pom.xml配置:
xml复制<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
由于Spring AI还处于快照阶段,需要添加Spring的Snapshot仓库:
xml复制<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
实际开发中发现,有时Snapshot仓库不稳定,可以配置多个镜像源作为备选。
Spring AI支持多种AI服务提供商,我们需要在application.yml中配置访问凭证。以OpenAI为例:
yaml复制spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
model: gpt-3.5-turbo
temperature: 0.7
关键参数说明:
model: 指定使用的模型版本temperature: 控制生成文本的随机性(0-2之间)max-tokens: 限制响应长度ChatClient是Spring AI的核心接口,它的构建器模式让API调用变得非常直观:
java复制@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder.build();
}
实际使用中,我们可以通过方法链式调用构建复杂提示:
java复制String response = chatClient.prompt()
.system("你是一个专业的Java技术专家")
.user("请解释Spring Bean的生命周期")
.call()
.content();
对于需要实时显示结果的场景,流式API是更好的选择:
java复制@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.stream()
.content();
}
前端可以通过EventSource监听这些实时事件:
javascript复制const eventSource = new EventSource('/stream?message=Hello');
eventSource.onmessage = (e) => {
console.log(e.data);
};
Spring AI可以将AI响应自动映射为POJO,这在处理结构化数据时特别有用:
java复制public record ProgrammingQuestion(String question, String language) {}
ProgrammingQuestion response = chatClient.prompt()
.user("我的问题是关于Java多线程的")
.call()
.entity(ProgrammingQuestion.class);
内置的ChatMemory接口可以自动维护对话上下文:
java复制@Bean
ChatMemory chatMemory() {
return new InMemoryChatMemory();
}
// 使用时会自动保留历史
String followUp = chatClient.prompt()
.user("基于我们之前的讨论,请给出更详细的解释")
.call()
.content();
java复制@Bean
public OpenAiChatClient openAiChatClient(OpenAiChatOptions options) {
return new OpenAiChatClient(options,
WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().responseTimeout(Duration.ofSeconds(30))
))
);
}
症状:401 Unauthorized错误
解决方法:
可能原因:
优化建议:
长时间运行的流式处理可能会积累内存,解决方法:
java复制@Bean
ChatMemory chatMemory() {
return new InMemoryChatMemory(20); // 限制最多20轮对话
}
在实际项目中,我通常会根据需求扩展基础功能:
一个实用的Prompt模板实现示例:
java复制public class TechSupportPromptTemplate implements PromptTemplate {
@Override
public String render(Map<String, Object> context) {
return """
你是一个专业的%s技术支持专家。
请用%s回答以下问题:
%s
""".formatted(
context.get("domain"),
context.get("language"),
context.get("question")
);
}
}
Spring AI为Java生态带来了全新的AI集成体验,它的设计既保留了Spring框架的优雅,又充分考虑了AI应用的特殊性。经过几个项目的实践验证,这种开发方式确实能显著提升生产效率。不过需要注意的是,由于AI服务的响应时间和成本因素,在设计架构时仍需谨慎考虑性能与成本的平衡。