问题现象

在Spring AI项目中注入:

public AiService(ChatClient.Builder builder) {
    this.chatClient = builder.build();
}

启动时却出现:

No qualifying bean of type
'org.springframework.ai.chat.client.ChatClient$Builder'
available

Spring AI官方说明,Spring Boot自动配置会为已配置的 ChatModel 创建一个原型作用域的 ChatClient.Builder。因此,找不到Bean通常不是ChatClient本身的问题,而是模型自动配置链路没有成立。


一、先确认依赖是否正确

以DeepSeek为例,Spring AI 2.0应使用:

    org.springframework.ai
    spring-ai-starter-model-deepseek

同时通过BOM统一版本:

            org.springframework.ai
            spring-ai-bom
            2.0.0
            pom
            import

常见错误包括:

  • 只引入 spring-ai-core
  • 只引入ChatClient API,没有引入模型Starter;
  • Starter版本与BOM版本混用;
  • 使用Spring AI 1.x依赖名称配合2.0配置;
  • Maven依赖没有刷新成功。

执行:

mvn dependency:tree | grep spring-ai

确认实际解析到的版本一致。


二、确认版本兼容

Spring AI 2.0.x支持Spring Boot 4.0.x和4.1.x。

推荐组合:

Spring Boot 4.1.0
Spring AI 2.0.0
JDK 21

如果Spring Boot 3.x项目强行引入Spring AI 2.0,自动配置可能无法正常生效。反过来,Spring Boot 4项目也不要继续复制Spring AI 1.x时期的旧配置。


三、确认模型自动配置没有被关闭

DeepSeek配置示例:

spring:
  ai:
    model:
      chat: deepseek
    deepseek:
      api-key: ${DEEPSEEK_API_KEY}
      chat:
        model: deepseek-v4-flash

Spring AI 2.0使用:

spring.ai.model.chat: deepseek

不要再使用已经移除的:

spring.ai.deepseek.chat.enabled: true

如果配置成:

spring.ai.model.chat: none

或者指定了一个与当前Starter不匹配的模型名,ChatModel不会创建,ChatClient.Builder自然也不会出现。


四、检查API Key

确保环境变量存在:

echo $DEEPSEEK_API_KEY

IDEA启动进程不一定自动继承终端中新设置的环境变量,应在运行配置中增加:

DEEPSEEK_API_KEY=sk-xxxxxxxx

不要设置一个伪默认密钥来“让应用先启动”,否则会把配置错误推迟到首次调用阶段。


五、检查组件扫描范围

启动类建议位于业务包上层:

package com.zyentor.springai;

@SpringBootApplication
public class Application {
}

业务类位于:

com.zyentor.springai.service
com.zyentor.springai.controller

如果启动类放在过深的包中,自定义配置类和业务Bean可能没有被扫描。


六、多模型场景下的Bean冲突

当项目同时接入多个模型时,可能出现:

expected single matching bean but found 2

更推荐基于不同 ChatModel 手动创建ChatClient:

@Configuration
public class MultiModelConfig {

    @Bean("deepSeekClient")
    ChatClient deepSeekClient(DeepSeekChatModel model) {
        return ChatClient.builder(model).build();
    }

    @Bean("openAiClient")
    ChatClient openAiClient(OpenAiChatModel model) {
        return ChatClient.builder(model).build();
    }
}

注入时显式使用:

public AiService(
        @Qualifier("deepSeekClient") ChatClient chatClient
) {
    this.chatClient = chatClient;
}

多模型项目中不要依赖“默认模型到底是哪一个”。


七、检查是否排除了自动配置

排查启动类中是否存在:

@SpringBootApplication(exclude = {
    // 某些AI自动配置类
})

测试类也要注意。@WebFluxTest默认只加载Web层,不会加载完整模型自动配置。

测试Controller时可以Mock业务服务:

@WebFluxTest(AiController.class)
class AiControllerTest {

    @MockBean
    AiService aiService;
}

测试真正的ChatClient集成时使用:

@SpringBootTest

并提供测试环境变量。


八、用Condition Evaluation Report定位

启动时增加:

java -jar app.jar --debug

或者:

debug: true

搜索:

DeepSeek
ChatClient
ChatModel

重点查看:

  • 哪个自动配置已匹配;
  • 哪个条件未满足;
  • 是否缺少Class;
  • 是否缺少属性;
  • 是否因为已有Bean而退让;
  • 是否被显式排除。

九、最小可运行示例

@RestController
public class AiController {

    private final ChatClient chatClient;

    public AiController(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    @GetMapping("/ai")
    public String chat(@RequestParam String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

十、排查清单

1. Spring Boot是否为4.0/4.1
2. Spring AI是否为2.0.0
3. 是否引入具体模型Starter
4. BOM与Starter版本是否一致
5. spring.ai.model.chat是否正确
6. API Key是否存在
7. 是否错误使用旧版enabled配置
8. 是否排除自动配置
9. 是否处于Web切片测试
10. 是否存在多模型Bean冲突
11. 查看Condition Evaluation Report

总结

找不到 ChatClient.Builder 的根因通常是:

ChatModel没有成功自动配置。

不要只在业务类上反复增加 @Bean@Component。先从依赖、版本、模型Starter、属性和自动配置条件逐层排查。