做过不少 AI 项目后你会发现,"只用一个模型"这件事越来越少见。DeepSeek 便宜、通义千问国内合规、Claude 代码能力强------不同场景用不同模型,或者主模型挂了自动切备用,这些都是真实需求。
这一节,我们来讲讲怎么在 Spring AI 里优雅地管理多模型,让业务代码完全不感知底层用的是哪个厂商。
一、前景回顾
早期我们在项目中配置了 Spring AI OpenAI Starter 的依赖如下:
1.1 依赖
<?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>
<!-- 继承 Spring Boot 父工程:统一管理 Spring Boot 相关依赖版本与插件配置 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.14</version>
<relativePath/>
</parent>
<groupId>com.edu</groupId>
<artifactId>edu-ai</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>21</java.version>
<spring-ai.version>1.1.5</spring-ai.version>
</properties>
<!-- Spring AI BOM:统一管理 spring-ai 所有子模块的版本 -->
<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>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot Web Starter:提供 Spring MVC、内嵌 Tomcat、RESTful 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--
Spring AI OpenAI Starter:支持 OpenAI 及所有兼容接口(DeepSeek、Moonshot 等)
引入后自动配置 ChatModel、EmbeddingModel 等 Bean,版本由 spring-ai-bom 统一管理
-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- Spring Boot Test Starter:提供 JUnit 5、Mockito、SpringBootTest 等测试支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.2 Yml配置
spring:
ai:
openai:
# 如果用 DeepSeek,改成 https://api.deepseek.com
# 如果用 OpenAI,改成 https://api.openai.com(或者不填,默认就是这个)
base-url: https://api.deepseek.com
api-key: ${DEEPSEEK_API_KEY} # 从环境变量读取,不要直接写在配置文件里
chat:
options:
model: deepseek-chat # DeepSeek-V3 的模型名
temperature: 0.7
此时整个应用只有一个 ChatModel,Spring AI 的自动配置工作得毫无波澜。
二、引入Spring AI Alibaba
2.1 核心官方文档入口
| 资源类型 | 地址 | 说明 |
|---|---|---|
| 官方文档网站 | https://java2ai.com/docs/1.0.0.2/get-started/chatbot | 最权威的入门和参考文档,包含聊天、工作流、智能体等完整指南。 |
| 项目GitHub仓库 | https://github.com/alibaba/spring-ai-alibaba | 源代码、版本发布、issue追踪,是了解项目开发动态的最权威地方。 |
| 官方博客与公告 | https://java2ai.com/blog | 发布新版本、核心特性解读和社区动态。 |
| 代码示例仓库 | https://github.com/springaialibaba/spring-ai-alibaba-examples | 包含完整的项目示例,帮助你快速上手实践。 |
| 云原生文档 | https://sca.aliyun.com/ai/ | 关于AI网关、可观测性、Nacos配置管理等生产环境部署的内容。 |
2.2引入依赖
添加如下依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>1.1.2.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.1.2.2</version>
</dependency>
</dependencies>
注意:spring-ai-alibaba-starter-dashscope需要指定对应的版本,因为spring-ai-alibaba-bom
中并没有管理它的版本
2.3 Yml配置
添加如下配置
spring:
ai:
dashscope:
api-key: xxx
chat:
options:
model: qwen-plus
三、启动服务,出现问题

***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 1 of method chatClientBuilder in org.springframework.ai.model.chat.client.autoconfigure.ChatClientAutoConfiguration required a single bean, but 2 were found:
- dashScopeChatModel: defined by method 'dashScopeChatModel' in class path resource [com/alibaba/cloud/ai/autoconfigure/dashscope/DashScopeChatAutoConfiguration.class]
- openAiChatModel: defined by method 'openAiChatModel' in class path resource [org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.class]
This may be due to missing parameter name information
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Ensure that your compiler is configured to use the '-parameters' flag.
You may need to update both your build tool settings as well as your IDE.
(See https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-6.1-Release-Notes#parameter-name-retention)
这是因为,在SpringAI启动时,会需要注入ChatModel对象,但是,现在由于引入了阿里云和OpenAI,会存在2个ChatModel对象实例,所以导致了报错。
3.1 分析问题
要想解决问题,首先我们需要找到启动时的自动配置类,在这里:

SpringAI就是由org.springframework.ai.autoconfigure.chat.client.ChatClientAutoConfiguration类完成自动配置的。
可以看到,在这个类中的chatClientBuilder方法,中注入了ChatModel对象,由于现在的Spring容器中存在2个实例,所以就报错了。

怎么解决这个问题呢?
3.2解决方法First
解决方法: 在SpringAIConfig中不通过ChatClient.Builder构建ChatClient对象,而是通过注入ChatModel的方式,来创建不同的ChatClient对象。
新构建ChatClient:(推荐)
package com.edu.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringAIConfig {
/**
* 配置 ChatClient
*/
@Bean
public ChatClient chatClient(@Qualifier("openAiChatModel") ChatModel chatModel,
Advisor loggerAdvisor) { // 日志记录器
return ChatClient.builder(chatModel)
.defaultAdvisors(loggerAdvisor) //添加 Advisor 功能增强
.build();
}
/**
* 日志记录器
* logging:
* level:
* org.springframework.ai.chat.client.advisor: DEBUG
*/
@Bean
public Advisor loggerAdvisor() {
return new SimpleLoggerAdvisor();
}
}
新写法通过 @Qualifier("openAiChatModel") 精确指定了用哪个模型来创建 ChatClient,彻底避开了歧义问题。
对比原来的写法(会报错):
package com.edu.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringAIConfig {
/**
* 配置 ChatClient
*/
@Bean
public ChatClient chatClient(ChatClient.Builder chatClientBuilder,
Advisor loggerAdvisor) { // 日志记录器
return chatClientBuilder
.defaultAdvisors(loggerAdvisor) //添加 Advisor 功能增强
.build();
}
/**
* 日志记录器
* logging:
* level:
* org.springframework.ai.chat.client.advisor: DEBUG
*/
@Bean
public Advisor loggerAdvisor() {
return new SimpleLoggerAdvisor();
}
}
3.3解决方法Second
排除用不到的自动配置,yml文件配置如下
spring:
autoconfigure:
exclude:
- org.springframework.ai.model.chat.client.autoconfigure.ChatClientAutoConfiguration
- org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration
为不同场景注册独立的 ChatClient:
package com.jichi.springaialibaba.config;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class MultiModelConfig {
@Bean("primaryChatClient")
@Primary
public ChatClient primaryChatClient(OpenAiChatModel openAiChatModel) {
return ChatClient.builder(openAiChatModel)
.defaultSystem("你是一个专业的助手")
.build();
}
@Bean("backupChatClient")
public ChatClient backupChatClient(DashScopeChatModel dashScopeChatModel) {
return ChatClient.builder(dashScopeChatModel)
.defaultSystem("你是一个专业的助手")
.build();
}
}
四、同理出现多个EmbeddingModel
项目中虽然没有直接使用 EmbeddingModel ,但通过 VectorStore 的自动配置间接依赖它
MilvusVectorStoreAutoConfiguration.vectorStore()
└── 需要注入一个 EmbeddingModel 参数
└── 但容器中有两个候选:
openAiEmbeddingModel (来自 OpenAI Starter)
dashscopeEmbeddingModel (来自 DashScope Starter)

4.1创建配置类
package com.edu.config;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class EmbeddingModelConfig {
/**
* 当存在多个 EmbeddingModel Bean (dashscopeEmbeddingModel, openAiEmbeddingModel) 时,
* 将 openAiEmbeddingModel 标记为 @Primary,避免自动注入时因歧义报错。
* 其他代码仍可通过 @Qualifier 指定使用非 Primary 的 Bean。
*/
@Bean
@Primary
public EmbeddingModel primaryEmbeddingModel(@Qualifier("openAiEmbeddingModel") EmbeddingModel embeddingModel) {
return embeddingModel;
}
}
这个配置类的作用是解决 Bean 冲突 ,将 openAiEmbeddingModel 标记为 @Primary。
4.2启动服务,进行测试
现在的配置已经正确地将 openAiEmbeddingModel 设为 @Primary,Spring 会优先使用它来创建 Milvus VectorStore。

启动成功!!!
五、小结
从单模型到多模型,Spring AI 引入多个厂商的 Starter 后,核心挑战就是 Bean 冲突。解决思路很清晰:
-
ChatModel 冲突 :绕开自动 Builder,直接用
@Qualifier注入具体模型构建 ChatClient。 -
EmbeddingModel 冲突 :定义一个
@PrimaryBean,明确告诉 Spring 默认用哪个。 -
想要多个 ChatClient:排除自动配置,手动注册 Bean。
搞定这些之后,你的应用就具备了"多模型共存"的能力,为后续的智能路由和降级打下了坚实的基础。而所有这些修改,几乎没有侵入业务代码,开发体验依旧丝滑。