Spring AI Alibaba 项目初始化:Maven依赖与YAML配置全解析
导读:上一篇完成了第一个 Hello World,本文将系统性地讲解企业级 Spring AI Alibaba 项目的配置体系------从 BOM 版本对齐到多模型并存,从 Profile 环境隔离到三级 ChatOptions 覆盖机制。读完这篇,你可以直接拿配置模板进公司项目用。
一、为什么配置问题是最大的"时间黑洞"
我见过很多团队在接入 Spring AI Alibaba 时,代码写不了几行,先被依赖冲突折腾了半天:Spring AI 版本和 Alibaba 版本对不上,BOM 没引好,同时接多个模型时 Bean 名字冲突...
这些问题的根源不是技术难度,而是没有一套清晰的配置认知。本文的目标就是把这些"隐形坑"全部翻出来,给你一张可复用的配置地图。
二、BOM 依赖管理:版本对齐的核心手段
2.1 什么是 BOM,为什么需要它
BOM(Bill of Materials)是 Maven 的一种依赖管理机制,本质上是一个只包含 <dependencyManagement> 的特殊 POM。引入 BOM 后,该 BOM 管辖的所有依赖版本都由 BOM 统一决定,你无需在每个依赖上手动填写版本号。
Spring AI Alibaba 涉及的依赖模块较多(dashscope、milvus、redis、mcp 等),版本不一致极易引发运行时异常。BOM 是最优雅的解法。
2.2 完整 BOM 配置示例
xml
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>ai-enterprise</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<java.version>17</java.version>
<!-- Spring AI Alibaba 版本,与 spring-ai 1.1.2 对齐 -->
<spring-ai-alibaba.version>1.1.2.2</spring-ai-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- ① Spring AI Alibaba BOM:管理所有 com.alibaba.cloud.ai 子模块版本 -->
<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>
<dependencies>
<!-- Web 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- ② DashScope(通义千问)模型接入 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot DevTools(可选,开发阶段热重载) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.3 多模型依赖配置
如果项目需要同时使用通义千问、OpenAI 以及本地 Ollama,依赖如下:
xml
<!-- 通义千问(阿里云百炼) -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- OpenAI(含 GPT-4 等) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- Ollama(本地模型,离线兜底用) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
注意 :同时引入多个模型 starter 时,Spring 容器里会存在多个
ChatModelBean,需要使用@Qualifier或配置primary来指定默认使用哪个,后文会详细说明。
2.4 版本兼容性速查表
+-------------------------+------------------+-------------------+
| Spring AI Alibaba | Spring AI | Spring Boot |
+-------------------------+------------------+-------------------+
| 1.1.2.2(当前推荐) | 1.1.2 | 3.3.x / 3.2.x |
| 1.1.2.1(有已知 bug) | 1.1.2 | 3.3.x / 3.2.x |
| 1.0.0.3 | 1.0.0 | 3.2.x |
| 1.0.0-M5.1(旧里程碑) | 1.0.0-M5 | 3.2.x |
+-------------------------+------------------+-------------------+
三、YAML 配置体系:从单文件到企业分层
3.1 基础配置文件结构
对于 AI 配置,建议将其独立到专属文件,而非堆在主 application.yml 里:
src/main/resources/
├── application.yml # 公共配置(端口、应用名等)
├── application-ai.yml # AI 相关配置(模型、参数等)
├── application-dev.yml # 开发环境配置
└── application-prod.yml # 生产环境配置
application.yml 主配置:
yaml
spring:
application:
name: ai-enterprise
profiles:
# 默认激活 dev + ai 两个 profile
active: dev,ai
server:
port: 8080
servlet:
encoding:
charset: UTF-8
force: true
3.2 application-ai.yml:AI 专属配置
yaml
# ==========================================
# Spring AI Alibaba 统一 AI 配置
# ==========================================
spring:
ai:
# ---- DashScope(通义千问)配置 ----
dashscope:
# API Key 通过环境变量注入,避免硬编码
api-key: ${AI_DASHSCOPE_API_KEY}
chat:
options:
# 默认模型(全局缺省值)
model: qwen-turbo
temperature: 0.7
top-p: 0.8
max-tokens: 2048
# 是否启用增量流式输出(仅流式接口有效)
incremental-output: true
# Embedding 模型配置
embedding:
options:
model: text-embedding-v3
# ---- OpenAI 配置(如需接入) ----
openai:
api-key: ${OPENAI_API_KEY:}
# 如使用代理或兼容接口,可修改 base-url
base-url: https://api.openai.com
chat:
options:
model: gpt-4o-mini
temperature: 0.7
# ---- Ollama 本地模型配置(离线兜底) ----
ollama:
base-url: http://localhost:11434
chat:
options:
model: llama3.2
temperature: 0.5
3.3 application-dev.yml:开发环境覆盖
yaml
spring:
ai:
dashscope:
# 开发环境可用测试 Key,降低成本
api-key: ${AI_DASHSCOPE_API_KEY_DEV:${AI_DASHSCOPE_API_KEY}}
chat:
options:
# 开发环境使用最便宜的模型
model: qwen-turbo
max-tokens: 1024
logging:
level:
com.alibaba.cloud.ai: DEBUG
org.springframework.ai: DEBUG
3.4 application-prod.yml:生产环境覆盖
yaml
spring:
ai:
dashscope:
chat:
options:
# 生产环境用能力更强的模型
model: qwen-plus
max-tokens: 4096
logging:
level:
com.alibaba.cloud.ai: WARN
org.springframework.ai: WARN
四、多模型并存:Bean 命名与注入策略
4.1 多 ChatModel 场景下的 Bean 冲突问题
当同时引入 DashScope 和 OpenAI 两个 starter,Spring 容器里会有两个 ChatModel 实现:DashScopeChatModel 和 OpenAiChatModel。直接 @Autowired ChatModel 会报 NoUniqueBeanDefinitionException。
解决方案有三种:
方案一:使用 @Qualifier 指定 Bean 名称(推荐)
java
@Service
public class MultiModelService {
private final ChatClient qwenClient;
private final ChatClient openaiClient;
public MultiModelService(
// Spring AI Alibaba 注册的 Builder Bean 名称
@Qualifier("dashscopeChatClientBuilder") ChatClient.Builder qwenBuilder,
@Qualifier("openAiChatClientBuilder") ChatClient.Builder openaiBuilder) {
this.qwenClient = qwenBuilder
.defaultSystem("你是通义千问助手")
.build();
this.openaiClient = openaiBuilder
.defaultSystem("You are a helpful assistant")
.build();
}
public String askQwen(String question) {
return qwenClient.prompt(question).call().content();
}
public String askOpenAI(String question) {
return openaiClient.prompt(question).call().content();
}
}
方案二:手动配置 @Primary 指定默认 Bean
java
@Configuration
public class AiModelConfig {
/**
* 将 DashScope 设为默认 ChatModel
* 其他地方 @Autowired ChatModel 时,优先注入此 Bean
*/
@Bean
@Primary
public ChatClient defaultChatClient(
@Qualifier("dashscopeChatModel") ChatModel dashScopeModel) {
return ChatClient.builder(dashScopeModel)
.defaultSystem("你是一个企业级智能助手")
.build();
}
}
方案三:基于 ChatModel 手动构建(最灵活)
java
@Configuration
public class ChatClientConfig {
@Bean("qwenChatClient")
public ChatClient qwenChatClient(DashScopeChatModel dashScopeModel) {
return ChatClient.builder(dashScopeModel)
.defaultSystem("你是通义千问,由阿里云提供支持")
.defaultOptions(DashScopeChatOptions.builder()
.withModel("qwen-max")
.withTemperature(0.7)
.build())
.build();
}
@Bean("openaiChatClient")
public ChatClient openaiChatClient(OpenAiChatModel openAiModel) {
return ChatClient.builder(openAiModel)
.defaultSystem("You are a helpful assistant powered by OpenAI")
.build();
}
}
4.2 DeepSeek-R1 接入配置
DeepSeek-R1 可通过兼容 OpenAI 接口的方式接入(百炼平台已上架 DeepSeek 模型):
yaml
spring:
ai:
openai:
# 使用阿里云百炼提供的 DeepSeek 兼容接口
api-key: ${AI_DASHSCOPE_API_KEY}
base-url: https://dashscope.aliyuncs.com/compatible-mode
chat:
options:
model: deepseek-r1
对应的 Java 配置:
java
@Bean("deepseekChatClient")
public ChatClient deepseekChatClient(
@Qualifier("openAiChatModel") OpenAiChatModel openAiModel) {
return ChatClient.builder(openAiModel)
.defaultSystem("你是 DeepSeek-R1,擅长深度推理和分析")
.build();
}
五、ChatOptions 三级覆盖机制详解
这是 Spring AI 体系中最容易被忽视但极其重要的特性,理解它能让你灵活控制每一次模型调用的行为。
5.1 三级结构示意
Level 1:YAML 全局配置(优先级最低)
spring.ai.dashscope.chat.options.temperature = 0.7
|
| (被 Level 2 覆盖)
v
Level 2:ChatClient Builder 构建时的 defaultOptions
ChatClient.builder(model)
.defaultOptions(DashScopeChatOptions.builder()
.withTemperature(0.8) // 覆盖 YAML 的 0.7
.build())
.build()
|
| (被 Level 3 覆盖)
v
Level 3:单次调用时的 .options(...)(优先级最高)
chatClient.prompt(msg)
.options(DashScopeChatOptions.builder()
.withTemperature(1.2) // 此次调用使用 1.2
.build())
.call()
5.2 实战:不同场景使用不同参数
java
@Service
@RequiredArgsConstructor
public class SmartChatService {
// 注入全局 ChatClient(使用 YAML 配置的默认参数)
private final ChatClient chatClient;
/**
* 代码生成场景:低温度,输出稳定确定
*/
public String generateCode(String requirement) {
return chatClient.prompt()
.system("你是一个资深 Java 开发工程师,只输出纯代码,不加解释")
.user(requirement)
.options(DashScopeChatOptions.builder()
.withModel("qwen-max") // 用最强模型
.withTemperature(0.1) // 极低温度,输出确定
.withMaxTokens(4096) // 允许较长代码输出
.build())
.call()
.content();
}
/**
* 创意写作场景:高温度,输出多样有趣
*/
public String creativeWrite(String topic) {
return chatClient.prompt()
.system("你是一个充满创意的文案策划师")
.user(topic)
.options(DashScopeChatOptions.builder()
.withModel("qwen-plus")
.withTemperature(1.2) // 高温度,充满创意
.withTopP(0.95)
.build())
.call()
.content();
}
/**
* 数据抽取场景:极低温度,结构化输出
*/
public String extractData(String rawText) {
return chatClient.prompt()
.system("从给定文本中提取结构化信息,以 JSON 格式输出")
.user(rawText)
.options(DashScopeChatOptions.builder()
.withTemperature(0.0) // 零温度,完全确定性
.withModel("qwen-turbo") // 简单任务用 turbo 节省成本
.build())
.call()
.content();
}
}
六、ChatClient 单例设计与线程安全
6.1 为什么 ChatClient 要是单例
ChatClient 本身是无状态的------它不持有会话历史,不存储中间结果。每次调用都是完整的一次请求-响应循环。因此,将它作为单例注入是完全安全的,同时避免了反复创建对象的开销。
java
@Configuration
public class ChatClientConfig {
/**
* 单例 ChatClient Bean
* 多线程并发调用时不会互相干扰,因为每次 .prompt() 都创建独立的调用上下文
*/
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder
.defaultSystem("你是企业级 AI 助手,回答简洁专业")
.defaultAdvisors(new SimpleLoggerAdvisor())
.build();
}
}
6.2 Advisor 链式拦截器
Advisor 是 Spring AI 中的拦截器机制,类似于 AOP,可以在请求前后注入逻辑:
java
@Bean
public ChatClient chatClientWithAdvisors(ChatClient.Builder builder) {
return builder
.defaultSystem("你是智能助手")
// Advisor 按注册顺序执行
// 1. 记忆增强:自动将历史消息附加到请求中
.defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
// 2. 日志追踪:记录每次请求和响应(开发阶段有用)
.defaultAdvisors(new SimpleLoggerAdvisor())
.build();
}
Advisor 执行流程:
用户请求
|
v
[Advisor 1: 日志记录请求]
|
v
[Advisor 2: 注入记忆上下文]
|
v
[发送到 DashScope 模型]
|
v
[收到模型响应]
|
v
[Advisor 2: 保存响应到记忆]
|
v
[Advisor 1: 日志记录响应]
|
v
返回给用户
七、开发工具配置优化
7.1 IDEA 插件推荐
在 IDEA 中安装以下插件,提升 AI 应用开发体验:
- Spring Boot Assistant :YAML 配置自动补全,支持
spring.ai.*属性提示; - Lombok:Lombok 注解支持(必装);
- Maven Helper:依赖分析,快速发现版本冲突;
- HTTP Client:内置 HTTP 测试,替代 Postman 测试接口。
7.2 Spring Boot DevTools 热重载
DevTools 默认不会热重载已加载的类,但对 YAML 配置文件的修改可以生效。对于 AI 应用,有一点需要注意:
java
// 不推荐:每次请求都 new ChatClient,无法享受 DevTools 热重载优势
@GetMapping("/chat")
public String chat(String msg) {
ChatClient client = ChatClient.builder(chatModel).build(); // 不要这样做
return client.prompt(msg).call().content();
}
// 推荐:注入单例 ChatClient,DevTools 修改配置后自动重载 Bean
@GetMapping("/chat")
public String chat(String msg) {
return chatClient.prompt(msg).call().content(); // 正确姿势
}
7.3 配置文件加密(生产环境)
生产环境下,即便通过环境变量注入,API Key 也可能出现在容器启动日志中。推荐使用 Jasypt 加密:
xml
<!-- pom.xml 添加 Jasypt -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
yaml
# application-prod.yml
spring:
ai:
dashscope:
# ENC() 包裹加密后的值
api-key: ENC(加密后的API-Key字符串)
jasypt:
encryptor:
# 加密密钥通过启动参数或环境变量传入,永远不要写在配置文件里
password: ${JASYPT_ENCRYPTOR_PASSWORD}
八、Profile 隔离最佳实践
一个成熟的企业项目,开发、测试、预发、生产四套环境的 AI 配置通常差异很大:
+----------+-------------+-----------+------------------+
| 环境 | 模型 | max-tokens | API Key 来源 |
+----------+-------------+-----------+------------------+
| dev | qwen-turbo | 1024 | 开发者个人 Key |
| test | qwen-turbo | 2048 | 测试专用 Key |
| staging | qwen-plus | 4096 | 预发 Key |
| prod | qwen-max | 8192 | 生产 Key(加密) |
+----------+-------------+-----------+------------------+
启动时激活对应 Profile:
bash
# 开发环境
java -jar app.jar --spring.profiles.active=dev,ai
# 生产环境
java -jar app.jar \
--spring.profiles.active=prod,ai \
--jasypt.encryptor.password=${JASYPT_PASSWORD}
九、完整配置参考模板
以下是一份可以直接复制使用的企业级配置模板:
yaml
# =============================================
# application.yml(主配置)
# =============================================
spring:
application:
name: my-ai-app
profiles:
active: ${SPRING_PROFILES_ACTIVE:dev},ai
server:
port: ${SERVER_PORT:8080}
servlet:
encoding:
charset: UTF-8
force: true
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: always
yaml
# =============================================
# application-ai.yml(AI 专属配置)
# =============================================
spring:
ai:
dashscope:
api-key: ${AI_DASHSCOPE_API_KEY}
chat:
options:
model: ${AI_DASHSCOPE_MODEL:qwen-turbo}
temperature: ${AI_TEMPERATURE:0.7}
top-p: 0.8
max-tokens: ${AI_MAX_TOKENS:2048}
incremental-output: true
embedding:
options:
model: text-embedding-v3
十、总结:配置管理要点速查
1. BOM 引入
→ 统一版本,避免冲突
→ spring-ai-alibaba-bom 版本与 spring-ai 严格对应
2. Starter 选择(1.1版)
→ DashScope:spring-ai-alibaba-starter-dashscope
→ OpenAI:spring-ai-starter-model-openai
→ Ollama:spring-ai-starter-model-ollama
3. 多模型并存
→ @Qualifier 指定 Builder 名称
→ @Primary 指定默认 Bean
→ 手动 @Bean 配置各模型 ChatClient
4. 配置分层
→ application.yml(公共)
→ application-ai.yml(AI 专属)
→ application-{env}.yml(环境覆盖)
5. API Key 安全
→ 开发:环境变量
→ 生产:Jasypt 加密 + 启动参数传密钥
6. ChatOptions 优先级
→ Call 级 > Builder defaultOptions 级 > YAML 全局
下一篇将深入 ChatClient 的流式输出、Advisor 机制、多轮对话管理与异常治理策略,进入真正的业务实战场景。
参考资料