一、Spring AI 是什么
Spring AI 是 Spring 官方推出的 AI 应用开发框架,主要目的是简化 AI 应用的开发。它提供了统一的 API,不管你用的是 DeepSeek、阿里百炼还是 OpenAI,代码写法都一样,只需要改配置就行。
目前 Spring AI 支持的主要功能:
- 统一的 ChatModel 接口,支持多种大模型
- 流式响应(Streaming Response)
- Function Call(工具调用)
- RAG(检索增强生成)
- MCP 协议支持
二、项目搭建
2.1 创建父工程
首先创建一个 Maven 父工程,统一管理版本。这里用的是 Spring Boot 3.5.7 和 Spring AI 1.0.1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>org.study.ai</groupId> <artifactId>spring-ai-study</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.5.7</version> </parent>
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring-ai.version>1.0.1</spring-ai.version> <spring-ai-alibaba.version>1.0.0.4</spring-ai-alibaba.version> </properties>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>${spring-ai.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-bom</artifactId> <version>${spring-ai-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
|
注意点:
- 必须使用 Java 17 或以上版本
dependencyManagement 中引入 BOM 后,子模块就不需要指定版本了
2.2 子模块依赖配置
DeepSeek 接入
在子模块的 pom.xml 中添加:
1 2 3 4
| <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-deepseek</artifactId> </dependency>
|
这个 starter 会自动配置 DeepSeekChatModel,只需要在配置文件中设置 API Key 就能用。
阿里百炼接入
1 2 3 4
| <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> </dependency>
|
阿里百炼的依赖是 spring-ai-alibaba 提供的,配置方式类似。
Ollama 接入(本地模型)
1 2 3 4
| <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-ollama</artifactId> </dependency>
|
Ollama 适合本地部署,不需要 API Key,但需要本地安装 Ollama 服务。
2.3 配置文件
在 application.properties 中配置:
1 2 3 4 5 6 7 8 9 10 11 12 13
| spring.application.name=quick-start
spring.ai.deepseek.api-key=sk-your-api-key-here spring.ai.deepseek.chat.options.model=deepseek-chat
spring.ai.dashscope.api-key=sk-your-api-key-here spring.ai.dashscope.chat.options.model=qwen-plus
logging.level.org.springframework.ai=INFO logging.level.org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor=DEBUG
|
配置说明:
api-key:从对应平台获取的 API Key
chat.options.model:使用的模型名称,DeepSeek 常用 deepseek-chat,阿里百炼常用 qwen-plus
- 日志级别建议开发时设为 DEBUG,生产环境设为 INFO
获取 API Key:
三、快速上手
3.1 同步调用
最简单的用法,直接调用 call() 方法:
1 2 3 4 5 6 7 8 9 10 11 12
| @SpringBootTest public class DeepSeekTest { @Autowired private DeepSeekChatModel deepSeekChatModel; @Test public void call() { String response = deepSeekChatModel.call("你好,你是谁"); System.out.println(response); } }
|
这种方式会等待 AI 完整回复后再返回,适合简单场景。如果回复很长,会等很久。
实际运行结果:
1
| 你好!我是 DeepSeek,一个由深度求索(DeepSeek)开发的 AI 助手...
|
3.2 流式调用
流式调用可以实时返回内容,用户体验更好。返回的是 Flux<ChatResponse>,需要处理响应流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Test public void testDeepSeekStream(@Autowired DeepSeekChatModel deepSeekChatModel) { DeepSeekChatOptions options = new DeepSeekChatOptions(); options.setTemperature(2.0); Prompt prompt = new Prompt("写一首上班加班太累的打油诗", options);
Flux<ChatResponse> stream = deepSeekChatModel.stream(prompt); stream.mapNotNull(e -> e.getResult().getOutput().getText()) .filter(Objects::nonNull) .toIterable() .forEach(System.out::print); }
|
关键点:
mapNotNull:提取每个响应中的文本内容,过滤掉 null
filter(Objects::nonNull):再次过滤,确保不为空
toIterable().forEach:转换为可迭代对象,逐个打印
实际效果:
会逐字逐句打印出来,而不是一次性返回全部内容。
3.3 深度思考模式
DeepSeek 支持深度思考模式(Reasoner),可以看到模型的思考过程。这在调试和优化 Prompt 时很有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Test public void testDeepSeekThink(@Autowired DeepSeekChatModel deepSeekChatModel) { DeepSeekChatOptions options = new DeepSeekChatOptions(); options.setTemperature(2.0); Prompt prompt = new Prompt("写一首上班加班太累的打油诗", options);
Flux<ChatResponse> stream = deepSeekChatModel.stream(prompt); stream.mapNotNull(e -> { AssistantMessage output = e.getResult().getOutput(); return output; }) .filter(Objects::nonNull) .toIterable() .forEach(e -> { if (Objects.nonNull(e.getMetadata().get("reasoningContent"))) { System.out.print(e.getMetadata().get("reasoningContent")); } if (Objects.nonNull(e.getText())) { System.out.print(e.getText()); } }); }
|
关键点:
- 思考内容在
metadata 的 reasoningContent 字段中
- 最终回复在
getText() 方法中
- 思考内容和最终回复是分开返回的
实际效果:
1 2
| [思考过程] 用户想要一首关于加班累的打油诗,我需要用幽默的方式表达... [最终回复] 上班加班累成狗,代码写到手发抖...
|
阿里百炼的思考模式
阿里百炼也支持思考模式,但需要显式开启:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| @Test public void testDashScopeThink(@Autowired DashScopeChatModel dashScopeChatModel) { DashScopeChatOptions options = new DashScopeChatOptions(); options.setTemperature(1.9); options.setEnableThinking(true); Prompt prompt = new Prompt("写一首上班加班太累的打油诗", options); Flux<ChatResponse> stream = dashScopeChatModel.stream(prompt); StringBuilder reasoningContent = new StringBuilder(); StringBuilder finalContent = new StringBuilder(); stream.mapNotNull(e -> { if (Objects.nonNull(e.getResult())) { return e.getResult().getOutput(); } return null; }) .filter(Objects::nonNull) .toIterable() .forEach(e -> { if (Objects.nonNull(e.getMetadata().get("reasoningContent"))) { reasoningContent.append(e.getMetadata().get("reasoningContent")); } if (Objects.nonNull(e.getText())) { finalContent.append(e.getText()); } }); System.out.println("【思考】" + reasoningContent); System.out.println("【回复】" + finalContent); }
|
区别:
- DeepSeek:默认支持思考模式
- 阿里百炼:需要设置
enableThinking(true) 才能看到思考过程
3.4 ChatOptions 参数说明
DeepSeekChatOptions
1 2 3 4
| DeepSeekChatOptions options = new DeepSeekChatOptions(); options.setTemperature(2.0); options.setMaxTokens(2000); options.setTopP(0.9);
|
参数建议:
temperature:创作类任务用 1.5-2.0,问答类用 0.7-1.0
maxTokens:根据需求设置,一般 1000-2000 够用
topP:一般用默认值就行
DashScopeChatOptions
1 2 3 4
| DashScopeChatOptions options = new DashScopeChatOptions(); options.setTemperature(1.9); options.setEnableThinking(true); options.setMaxTokens(2000);
|
四、常见问题
4.1 API Key 配置不生效
问题: 配置了 API Key 但启动报错,提示找不到配置。
原因:
- API Key 配置错误
- 配置文件路径不对
- 环境变量覆盖了配置文件
解决:
- 检查配置文件中的 Key 是否正确
- 确认配置文件在
src/main/resources 目录下
- 检查是否有环境变量覆盖(如
SPRING_AI_DEEPSEEK_API_KEY)
4.2 流式调用没有输出
问题: 调用 stream() 方法后没有任何输出。
原因:
解决:
1 2 3 4 5 6 7 8 9
| Flux<ChatResponse> stream = deepSeekChatModel.stream(prompt);
stream.mapNotNull(...) .filter(...) .toIterable() .forEach(...);
|
4.3 思考模式看不到思考内容
问题: 开启了思考模式但看不到思考过程。
原因:
- DeepSeek:某些模型不支持思考模式
- 阿里百炼:忘记设置
enableThinking(true)
解决:
- DeepSeek:确认使用的是支持思考的模型(如
deepseek-reasoner)
- 阿里百炼:必须显式设置
options.setEnableThinking(true)
4.4 中文乱码
问题: 返回的中文内容乱码。
原因:
解决:
1 2 3 4
| @GetMapping(value = "/stream", produces = "text/stream;charset=utf-8") public Flux<String> streamChat(...) { }
|
4.5 依赖冲突
问题: 引入 Spring AI 后出现依赖冲突。
原因:
- Spring Boot 版本不兼容
- 其他依赖版本冲突
解决:
- 确认 Spring Boot 版本是 3.x(Spring AI 1.0.1 需要 Spring Boot 3.5+)
- 使用
mvn dependency:tree 查看依赖树
- 在父工程中统一管理版本
五、总结
- 统一接口:Spring AI 提供了统一的
ChatModel 接口,切换模型只需要改配置
- 同步 vs 流式:简单场景用同步调用,需要实时反馈用流式调用
- 思考模式:DeepSeek 默认支持,阿里百炼需要显式开启
- 配置要点:API Key 和模型名称是必须的,其他参数按需设置
- 常见坑:流式调用必须订阅、中文编码问题、依赖版本冲突
下一篇文章会介绍 ChatClient 的使用,这是 Spring AI 提供的高级 API,比直接使用 ChatModel 更方便。