一句话先说结论:
No qualifying bean of type 'ChatModel'或Unsupported model provider,几乎都是“模型基础设施没装配起来”——要么压根没引入对应厂商的 starter,要么application.yml里 api-key / model 没配好,要么版本没走 BOM 管理导致内部模块版本对不上。三步排查:依赖、配置、自动配置是否生效。
背景
Spring AI 采用「厂商即模块」的设计——你想用 OpenAI 就引 OpenAI 的 starter,想用 Ollama 就引 Ollama 的 starter。这个 starter 自带自动配置类(如 OpenAiAutoConfiguration),它负责在容器里注册 ChatModel、ChatClient 这些 Bean。所以链条是:加依赖 → 配属性 → 自动配置注册 Bean → 你在代码里注入。任何一环断了,注入时就报 bean 找不到。
现象
启动或注入时常见的三种报错:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.springframework.ai.chat.ChatModel'
java.lang.IllegalArgumentException: Unsupported model provider: 'openai'
Could not autowire. No beans of 'OpenAiChatModel' type found.
三者表象不同,但都指向同一件事:容器里根本没有 ChatModel 的实现 Bean。
根因分析
坑 1:没引入厂商 starter
没 starter 就没有自动配置入口。以 OpenAI 为例(注意 Spring AI 1.0 之后 artifact 名改了):
<!-- Spring AI 1.x 起的命名 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
旧版本(0.8.x 时代)叫 spring-ai-openai-spring-boot-starter,不同版本之间 artifact 名不一样,这是后面「版本升级」那篇的重点。这里先确认:你引的那个 starter 是不是当前版本对应的名字。
坑 2:版本没走 BOM,内部模块版本对不上
Spring AI 是快速迭代的项目,自己手动指定单个依赖版本,很容易出现“你写的版本和内部拉到的模块版本不一致”,导致 ClassNotFoundException 或 bean 不注册。正确做法是用 BOM 统一管理,别单独写版本号:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
用 Milestone/Snapshot 版本还要额外配 Spring 仓库:
<repositories>
<repository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
坑 3:配置属性没写对
只引 starter 还不够,spring.ai.* 配置也要对:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4o-mini
temperature: 0.2
两个高频拼写错误:api-key 写成 api_key(下划线 vs 中划线),模型名写错(比如实际是 gpt-4o-mini 写成了 gpt-4-mini)。这类错往往导致 OpenAiChatModel 构造失败后静默跳过 bean 注册,日志里不算显眼,特别难查。
坑 4:手动声明 ChatClient 没绑定 ChatModel
绕过自动配置自己写 @Bean ChatClient 时,必须注入底层 ChatModel:
@Bean
public ChatClient chatClient(ChatModel chatModel) {
return ChatClient.builder()
.model(chatModel) // 必须显式绑定
.build();
}
ChatClient.builder().build() 不带 model,内部会尝试从上下文字典找 ChatModel,初始化顺序不对就失败——这种写法只适合测试里手动塞 model。
解决方案
按顺序排查这三步
- 依赖:确认引入了当前版本对应的厂商 starter,并用 BOM 管理版本。
- 配置:
spring.ai.openai.api-key、chat.options.model拼写正确、非空。 - 自动配置:启动时加
--debug,在CONDITIONS EVALUATION REPORT里搜OpenAiAutoConfiguration,看它有没有被排除(excluded)或条件不满足(did not match)。
也可以用代码直接确认 bean 是否存在:
String[] names = context.getBeanNamesForType(ChatModel.class);
System.out.println(Arrays.toString(names)); // 空数组说明自动配置没生效
一个真实的自定义配置坑
如果你在 @Configuration 里用 @Value 读 api-key,却发现注入进来是 null,甚至日志打了 Cannot enhance @Configuration bean definition since its singleton instance has been created too early——这是 Spring AI 的配置类初始化得太早,早于属性绑定。解决是把配置改用 @ConfigurationProperties + 构造器注入,而不是 @Value 字段注入。
小结
- 报 bean 找不到,别先怀疑注入语法,先看依赖和自动配置。
- 记住三件套:正确的厂商 starter + BOM 版本管理 + 正确拼写的
spring.ai.*配置。 - 排障用
--debug看CONDITIONS EVALUATION REPORT,比翻日志快得多。 - 手写
ChatClientBean 记得注入ChatModel。