AI时代,Python程序员在狂欢,Java程序员在焦虑。但Spring AI 1.0的发布,终于让Java开发者也能优雅地接入大模型了。
大家好,我是卷毛。
作为9年Java老兵,我承认之前看Python那套AI生态是有些羡慕的。但Spring AI 1.0正式发布后,我用一个下午就完成了大模型接入——全程Java,零Python代码。
这篇文章,手把手教你从0到1接入大模型,附完整可运行代码。
一、Spring AI是什么?
一句话:Spring AI是Spring官方推出的AI应用开发框架,让你用Spring的方式开发AI应用。
它的核心能力:
| 能力 | 说明 |
|---|---|
| Chat Client | 统一的大模型对话接口,支持OpenAI/Claude/通义千问等 |
| Embedding | 文本向量化,用于RAG和语义搜索 |
| Vector Store | 向量数据库集成(Milvus/Pinecone/Redis等) |
| Function Calling | 让大模型调用你的Java方法 |
| RAG | 检索增强生成,让AI基于你的私有数据回答问题 |
| Memory | 对话记忆管理 |
| Tools | 工具调用框架 |
最大优势:和Spring Boot无缝集成,你熟悉的依赖注入、配置管理、Actuator监控全都能用。
二、5分钟快速接入
Step 1:添加依赖
<!-- pom.xml -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version>
</parent>
<dependencies>
<!-- Spring AI核心 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- 向量数据库(用于RAG) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-redis</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Step 2:配置大模型
# application.yml
spring:
ai:
openai:
api-key: ${AI_API_KEY}
base-url: https://api.deepseek.com # 支持DeepSeek/通义千问/OpenAI等
chat:
options:
model: deepseek-chat
temperature: 0.7
max-tokens: 2000
embedding:
options:
model: text-embedding-v1
Step 3:第一个AI对话
@Service
public class ChatService {
private final ChatClient chatClient;
// Spring自动注入,和注入其他Bean一样简单
public ChatService(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("你是一个专业的Java技术助手,回答简洁准确。")
.build();
}
public String chat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
// 流式输出(打字机效果)
public Flux<String> chatStream(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.stream()
.content();
}
}
@RestController
@RequestMapping("/api/ai")
public class ChatController {
private final ChatService chatService;
public ChatController(ChatService chatService) {
this.chatService = chatService;
}
@PostMapping("/chat")
public Map<String, String> chat(@RequestBody Map<String, String> request) {
String answer = chatService.chat(request.get("message"));
return Map.of("answer", answer);
}
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String message) {
return chatService.chatStream(message);
}
}
就这样,你的Java应用就能和AI对话了。 是不是比想象的简单?
三、进阶:让AI调用你的Java方法(Function Calling)
这才是最实用的功能——让大模型调用你定义的Java方法。
场景:智能客服,AI能查订单状态
// 1. 定义工具函数
@Bean
public Function<OrderQueryRequest, OrderQueryResponse> queryOrderStatus(OrderService orderService) {
return request -> {
Order order = orderService.findById(request.orderId());
return new OrderQueryResponse(
order.getId(),
order.getStatus().toString(),
order.getCreatedAt().toString()
);
};
}
// 2. 记录定义
public record OrderQueryRequest(String orderId) {}
public record OrderQueryResponse(String orderId, String status, String createdAt) {}
// 3. 使用
@Service
public class CustomerService {
private final ChatClient chatClient;
public String handleCustomerQuestion(String question) {
return chatClient.prompt()
.user(question)
.functions("queryOrderStatus") // 绑定工具函数
.call()
.content();
}
}
测试一下:
// 用户问:"帮我查一下订单ORD-2026-001的状态"
// AI会自动:
// 1. 识别意图:用户想查订单
// 2. 调用queryOrderStatus("ORD-2026-001")
// 3. 拿到结果后组织自然语言回复
// AI回复:"您的订单ORD-2026-001当前状态为已发货,下单时间为2026年6月20日。"
AI自动理解了用户意图,并调用了你的Java方法! 这就是Function Calling的威力。
四、RAG实战:让AI基于你的私有数据回答问题
场景:企业内部知识库问答
@Service
public class KnowledgeBaseService {
private final VectorStore vectorStore;
private final ChatClient chatClient;
// 1. 导入文档到向量数据库
public void importDocuments(List<Document> documents) {
vectorStore.add(documents);
}
// 2. RAG问答
public String ask(String question) {
// 检索相关文档
List<Document> relevantDocs = vectorStore.similaritySearch(
SearchRequest.builder()
.query(question)
.topK(3) // 取最相关的3个文档
.similarityThreshold(0.7)
.build()
);
// 拼接上下文
String context = relevantDocs.stream()
.map(Document::getText)
.collect(Collectors.joining("\n\n"));
// 构造prompt
return chatClient.prompt()
.system("""
你是企业知识库助手。基于以下参考资料回答问题。
如果参考资料中没有答案,请说"我无法回答这个问题"。
不要编造信息。
参考资料:
""" + context)
.user(question)
.call()
.content();
}
}
导入PDF文档
@Component
public class DocumentImporter {
private final VectorStore vectorStore;
public void importPdf(String pdfPath) {
// Spring AI内置PDF读取
PagePdfDocumentReader reader = new PagePdfDocumentReader(pdfPath);
List<Document> documents = reader.get();
// 文本分块(避免单块太长)
TokenTextSplitter splitter = new TokenTextSplitter();
List<Document> chunks = splitter.apply(documents);
// 写入向量数据库
vectorStore.add(chunks);
}
}
五、对话记忆管理
@Service
public class ChatMemoryService {
private final ChatClient chatClient;
private final ChatMemory chatMemory;
public ChatMemoryService(ChatClient.Builder builder) {
this.chatMemory = new InMemoryChatMemory(); // 生产环境用Redis
this.chatClient = builder
.defaultSystem("你是Java技术助手。")
.defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
.build();
}
// 带记忆的对话
public String chat(String sessionId, String message) {
return chatClient.prompt()
.user(message)
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, sessionId))
.call()
.content();
}
}
测试效果:
用户: 我叫张三
AI: 你好,张三!
用户: 我叫什么名字?
AI: 你叫张三。(← 记住了!)
六、完整项目结构
spring-ai-demo/
├── src/main/java/com/juanmao/ai/
│ ├── config/
│ │ └── AiConfig.java # AI相关配置
│ ├── controller/
│ │ └── ChatController.java # 对话接口
│ ├── service/
│ │ ├── ChatService.java # 对话服务
│ │ ├── KnowledgeBaseService.java # RAG服务
│ │ └── FunctionCallService.java # 工具调用服务
│ ├── function/
│ │ ├── OrderQueryFunction.java # 查订单工具
│ │ └── WeatherQueryFunction.java # 查天气工具
│ └── Application.java
├── src/main/resources/
│ └── application.yml
└── pom.xml
七、成本控制建议
大模型API按token收费,不注意的话账单会爆炸:
// 1. 设置token上限
spring.ai.openai.chat.options.max-tokens=500
// 2. 使用缓存减少重复调用
@Cacheable(value = "ai-responses", key = "#prompt.hashCode()")
public String chat(String prompt) {
return chatClient.prompt().user(prompt).call().content();
}
// 3. 轻量级问题用小模型,复杂问题用大模型
public String smartRoute(String question) {
if (question.length() < 50) {
// 简单问题用轻量模型
return lightChatClient.prompt().user(question).call().content();
}
// 复杂问题用主力模型
return chatClient.prompt().user(question).call().content();
}
// 4. 监控token使用量
// 通过Actuator endpoint查看:/actuator/metrics/spring.ai.token.usage
写在最后
Spring AI让Java开发者终于不用在AI时代掉队了。你不需要学Python,不需要理解PyTorch,用你熟悉的Spring就能构建AI应用。
我目前已经用Spring AI在项目里实现了:
- 智能客服(Function Calling + RAG)
- 代码review助手
- 运维告警智能分析
- 内部知识库问答
后续会出系列教程,逐个深入讲解。
📌 我是卷毛,9年Java开发,正在探索Java + AI的最佳实践。
这篇文章的代码可以直接跑起来,收藏备用。
关注《卷毛的技术笔记》,Spring AI系列持续更新中! 🔥
你在用Spring AI了吗?有什么问题评论区聊 👇