前言
随着 AI 大模型技术的日益成熟,Spring 官方推出了 Spring AI 框架,为开发者提供了统一的大模型集成方案。开发者无需再通过繁琐的 HTTP 请求调用不同的模型 API,只需引入相应依赖,即可快速实现与各类大模型的对接。
准备
spring ai 集成最低版本要求
- spring boot 版本 3.x
- jdk 版本 17+
本文使用 spring ai 依赖版本为 1.1.0(该版本更新时间为 2025 年 11 月 22 号)
模型选择
全球大模型市场呈现三足鼎立的局面,分别由 OpenAI 的 ChatGPT、Anthropic 的 Claude 以及 Google 的 Gemini 占据前三。与此同时,国内也涌现出了优秀的大模型产品,如 DeepSeek 和智谱的 GLM,在技术能力上毫不逊色。然而,Google 的 Gemini 目前限制了中国地区的服务无法调用(pass)。
本文主要集成 4 种大模型
- openai 公司 ChatGPT 大模型 (新账号送 5 美元免费额度)
- anthropic 公司 Claude 大模型 (无免费额度)
- deepseek 公司 DeepSeek 大模型 (无免费额度)
- zhipu 公司 GLM 大模型 (新账号送 千万 token 相当友好,邀请新人注册还送,对于大家测试调试妥妥够用了)
实践
完整源码获取:GitHub - RemainderTime/spring-ai-lab: LLM 相关对接实现 ai-models-chat 模块
注:本文只实现大模型文本对话功能,多模块不在本文实现。
本项目在多模块项目中管理,方便版本统一。
本文仅说明核心功能源码实现,细节请参考上面源码。

依赖引入
1: 父 pom.xml 依赖
xml
<dependencyManagement>
<dependencies>
<!-- 引入 Spring AI bom 统一版本 -->
<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>
2: ai-models-chat 模型 pom.xml 依赖引入
直接引入 4 个大模型依赖
xml
<dependencies>
<!-- 集成anthropic公司依赖 用于claude 模型-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-anthropic</artifactId>
</dependency>
<!-- 集成openai公司依赖 用于gpt 模型-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- 集成zhipu ai公司依赖 用于GLM 模型-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>
<!-- 集成deepseek公司依赖 用于DeepSeek 模型-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-deepseek</artifactId>
</dependency>
</dependencies>
配置 yml 文件
spring 对支持的大模型做了统一的规范
yml
spring:
ai:
anthropic:
api-key: xxx
options:
model: claude-3-5-sonnet-20241022
temperature: 0.7
openai:
api-key: xxx
chat:
options:
model: gpt-4o-mini
temperature: 0.7
zhipuai:
api-key: xxx
chat:
options:
model: glm-4.6
temperature: 0.7
deepseek:
api-key: xxx
chat:
options:
model: deepseek-chat
temperature: 0.7
- api-key: 调用大模型的密钥(去对应大模型网站创建申请)
- model: 模型大模型版本(也可在代码中动态设置)
- temperature:用于控制模型的创意程度(0-2 之间),越小返回的内容越固定,越大创意程度越高可能偏离想要的答案,根据业务情况设置,一般设置 0.7 适中
API 接口实现
每种模型显示两种接口:
- 直接应答模式
- 流式应答模式(SSE 模式)
1: chatGPT 接口
java
@RestController
@RequestMapping("/ai/chatgpt")
public class ChatGPTModelController {
@Autowired
private OpenAiChatModel chatModel;
/**
* chatgpt 模型直接调用
*
* @return
*/
@GetMapping("/call/chat")
public String callChat(@RequestParam String message, @RequestParam(defaultValue = "gpt-4o-mini") String model) {
ChatResponse response = chatModel.call(
new Prompt(
message,
OpenAiChatOptions.builder()
.model(model)
.temperature(0.7)
.build()
));
return response.getResult().getOutput().getText();
}
/**
* chatgpt 模型流式调用
*
* @return
*/
@GetMapping(value = "/stream/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> streamChat(@RequestParam String message, @RequestParam(defaultValue = "gpt-4o-mini") String model) {
return chatModel.stream(
new Prompt(message, OpenAiChatOptions.builder().model(model).build())
)
.map(chatResponse -> {
String text = chatResponse.getResults()
.stream()
.filter(r -> r.getOutput().getText() != null)
.map(r -> r.getOutput().getText())
.findFirst()
.orElse("");
return ServerSentEvent.<String>builder()
.data(text)
.build();
})
.concatWith(Flux.just(
ServerSentEvent.<String>builder()
.data("[DONE]")
.build()
))
.doOnError(Throwable::printStackTrace);
}
/**
* chatgpt 模型直接调用(图片内容)
* 只支持 GPT_4_O 或 GPT_4_TURBO 模型
*
* @return
*/
@PostMapping("/call/chatImg")
public String callChatImg(@RequestParam String message,
@RequestParam(defaultValue = "gpt-4o") String model,
@RequestParam MultipartFile imageFile) {
// 读取图片
byte[] imageBytes = null;
try {
imageBytes = imageFile.getBytes();
} catch (IOException e) {
throw new RuntimeException(e);
}
Resource imageResource = new ByteArrayResource(imageBytes);
// 创建消息列表
List<org.springframework.ai.chat.messages.Message> messages = new ArrayList<>();
// 添加文本消息
messages.add(new UserMessage(message));
// 添加图片消息
messages.add(new UserMessage(imageResource));
// 调用模型
ChatResponse response = chatModel.call(
new Prompt(
messages,
OpenAiChatOptions.builder()
.model(model)
.build()
)
);
return response.getResult().getOutput().getText();
}
2: Claude 模型调用
java
@RestController
@RequestMapping("/ai/claude")
public class ClaudeModelController {
@Resource
private AnthropicChatModel chatModel;
/**
* claude 模型直接调用
* @return
*/
@GetMapping("/call/chat")
public ChatResponse callChat(@RequestParam String message, @RequestParam(defaultValue = "claude-3-7-sonnet-latest")String model) {
return chatModel.call(
new Prompt(
message,
AnthropicChatOptions.builder()
.model(model)
.temperature(0.7)
.build()
));
}
/**
* claude 模型流式调用
* @return
*/
@GetMapping(value = "/stream/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ChatResponse> streamChat(@RequestParam String message, @RequestParam(defaultValue = "claude-3-7-sonnet-latest")String model) {
return chatModel.stream(
new Prompt(
message,
AnthropicChatOptions.builder()
.model(model)
.temperature(0.7)
.build()
));
}
}
3: DeepSeek 模型调用
java
@RestController
@RequestMapping("/ai/deepseek")
public class DeepSeekModelController {
@Resource
private DeepSeekChatModel chatModel;
/**
* deepseek 模型直接调用
*
* @return
*/
@GetMapping("/call/chat")
public String callChat(@RequestParam String message, @RequestParam(defaultValue = "deepseek-chat") String model) {
ChatResponse response = chatModel.call(
new Prompt(
message,
DeepSeekChatOptions.builder()
.model(model)
.temperature(0.7)
.build()
));
return response.getResult().getOutput().getText();
}
/**
* deepseek 模型流式调用
*
* @return
*/
@GetMapping(value = "/stream/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> streamChat(@RequestParam String message, @RequestParam(defaultValue = "deepseek-chat") String model) {
return chatModel.stream(
new Prompt(message, DeepSeekChatOptions.builder().model(model).build())
)
.map(chatResponse -> {
String text = chatResponse.getResults()
.stream()
.filter(r -> r.getOutput().getText() != null)
.map(r -> r.getOutput().getText())
.findFirst()
.orElse("");
return ServerSentEvent.<String>builder()
.data(text)
.build();
})
.concatWith(Flux.just(
ServerSentEvent.<String>builder()
.data("[DONE]")
.build()
))
.doOnError(Throwable::printStackTrace);
}
}
4:GLM 模型调用
java
@RestController
@RequestMapping("/ai/glm")
public class GLMModelController {
@Resource
private ZhiPuAiChatModel chatModel;
/**
* glm 模型直接调用
*
* @return
*/
@GetMapping("/call/chat")
public String callChat(@RequestParam String message, @RequestParam(defaultValue = "glm-4.6") String model) {
ChatResponse response = chatModel.call(
new Prompt(
message,
ZhiPuAiChatOptions.builder()
.model(model)
.temperature(0.7)
.build()
));
return response.getResult().getOutput().getText();
}
/**
* glm 模型流式调用
*
* @return
*/
@GetMapping(value = "/stream/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> streamChat(@RequestParam String message, @RequestParam(defaultValue = "glm-4.6") String model) {
return chatModel.stream(
new Prompt(message, ZhiPuAiChatOptions.builder().model(model).build())
)
.map(chatResponse -> {
String text = chatResponse.getResults()
.stream()
.filter(r -> r.getOutput().getText() != null)
.map(r -> r.getOutput().getText())
.findFirst()
.orElse("");
return ServerSentEvent.<String>builder()
.data(text)
.build();
})
.concatWith(Flux.just(
ServerSentEvent.<String>builder()
.data("[DONE]")
.build()
))
.doOnError(Throwable::printStackTrace);
}
}
一些思考⁉️
我们应该理性对待 AI 工具。不能将整个项目的功能业务全权交由 AI 处理,因为 AI 并不真正理解项目的全局设计、架构约束和业务复杂性。盲目依赖 AI 生成的代码,会增加代码审查、修改和测试的成本,其合理性也难以保证。
AI 作为特定功能模块或业务逻辑的 辅助工具,用来快速提供解决思路或代码框架,但核心的架构设计、设计模式的选用、并发控制、系统整体优化等,仍需由经验丰富的开发者主导。过度依赖工具只会适得其反,削弱开发者的思考能力和解决问题的能力。
AI 工具只是辅助手段,用于加速特定模块的开发,但不能替代人的 ****架构思维和全局考量。理性、有节制地使用 AI,充分发挥其优势同时规避风险,才是正确的态度。
总结
与其追捧各类 AI 开发工具,不如主动掌握和应用 AI 大模型技术。作为开发者,我们应该利用大模型的强大能力来解决实际问题、优化日常工作流程,从而在竞争中脱颖而出。实际上,无论选用哪款大模型,对于大多数日常任务的处理效果差异不大------关键在于如何创意性地应用,而非被特定工具绑定。