1. 概述

ChatClient 是构建在 ChatModel 之上的高层接口,是大语言模型(LLM)交互的统一入口,支持 ToolRAGMemoryAdvisor 等高级功能。

核心源码如下:

public interface ChatClient {
    // 创建 ChatClient 实例
    static ChatClient create(ChatModel chatModel)
    static ChatClient create(ChatModel chatModel, ObservationRegistry observationRegistry)
    
    // 构建器模式
    static Builder builder(ChatModel chatModel)
    
    // 提示词入口
    ChatClientRequestSpec prompt()
    ChatClientRequestSpec prompt(String content)
    ChatClientRequestSpec prompt(Prompt prompt)
    
    // 创建变异构建器
    Builder mutate()
}

DefaultChatClientChatClient 接口的标准默认实现:

public class DefaultChatClient implements ChatClient {
    private static final ChatClientObservationConvention DEFAULT_CHAT_CLIENT_OBSERVATION_CONVENTION = new DefaultChatClientObservationConvention();
    private static final TemplateRenderer DEFAULT_TEMPLATE_RENDERER = StTemplateRenderer.builder().build();
    private static final ChatClientMessageAggregator CHAT_CLIENT_MESSAGE_AGGREGATOR = new ChatClientMessageAggregator();
    private final DefaultChatClientRequestSpec defaultChatClientRequest;

    public DefaultChatClient(DefaultChatClientRequestSpec defaultChatClientRequest) {
        Assert.notNull(defaultChatClientRequest, "defaultChatClientRequest cannot be null");
        this.defaultChatClientRequest = defaultChatClientRequest;
    }

    public ChatClient.ChatClientRequestSpec prompt() {
        return new DefaultChatClientRequestSpec(this.defaultChatClientRequest);
    }
    // ......
}

2. 基础用法

2.1 创建对话客户端

支持使用 ChatClient.BuilderChatClient.create() 方法手动创建:

// 1. 创建 ChatModel
OpenAiChatModel chatModel = new OpenAiChatModel(
    OpenAiChatOptions.builder()
        .apiKey("your-api-key")
        .model("gpt-4")
        .temperature(0.7)
        .build()
);

// 2. 创建 ChatClient
ChatClient chatClient = ChatClient.create(chatModel);

// 3. 或使用建造者
ChatClient chatClient = ChatClient.builder(chatModel)
    .defaultSystem("你是一个翻译助手")
    .build();

Spring AI 也提供了 Spring Boot 自动配置的 ChatClient.Builder 实例,可以直接注入到业务类中调用其 build() 方法创建:

@RestController
class MyController {

    private final ChatClient chatClient;

    public MyController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }
}

ChatClientAutoConfiguration 自动配置类中,可以找到该 Bean
在这里插入图片描述
提示:但是这里有个问题,所依赖的 ChatModel 如果存在多个类型实例,就会报错 required a single bean, but 3 were found ,所以仅仅适用于只有一个 ChatModel 实例的场景。

2.2 默认配置项

ChatClient.Builder 提供了一系列链式方法来配置 ChatClient 的各种默认行为和参数:

  • defaultAdvisors:默认增强器,可用于请求拦截、参数校验、日志记录等增强逻辑。
  • defaultOptions:默认对话配置,比如请求超时时间、使用的 AI 模型、请求重试策略等。
  • defaultUser:默认的用户输入内容,支持直接传字符串、从文件 / 资源读取,或通过配置规范自定义。
  • defaultSystem:默认的系统提示词。
  • defaultTemplateRenderer:配置的模板渲染器。
  • defaultTools**:用于配置聊天客户端可调用的工具、工具回调、工具上下文等。
    示例代码:
        ChatClient chatClient = ChatClient.builder()
                // 配置系统提示
                .defaultSystem("你是一个Java编程助手,回答简洁明了")
                // 配置默认用户提示
                .defaultUser("解释建造者模式的使用场景")
                // 配置聊天选项(如超时、模型)
                .defaultOptions(ChatOptions.builder().timeout(30000).model("gpt-3.5-turbo").build())
                // 配置工具
                .defaultToolNames("code_checker")
                // 构建最终实例
                .build();

2.3 Fluent API

ChatClient 采用 Fluent API 设计,提供了一种链式调用、表达力强的编程方式。

核心调用链结构如下:

阶段 方法 作用
入口阶段 ChatClient 获取 ChatClient 实例
构建请求阶段 .prompt() 开始调用链,构建提示词
配置阶段 .options() 配置模型参数
执行阶段 .call()/ .stream() 执行同步或异步流式调用
结果处理阶段 .content() 获取文本内容或完整结果对象

示例代码:

// 完整调用链示例
String result = chatClient                    // ← 入口
    .prompt("解释Spring Bean的作用域")        // ← 开始构建请求 ← 添加消息
    .options(ChatOptions.builder()            // ← 配置模型参数
        .temperature(0.3)
        .maxTokens(500)
        .build())
    .call()                                   // ← 执行同步调用
    .content();                               // ← 获取文本结果

// 流式调用示例
Flux<String> stream = chatClient
    .prompt()
    .user("写一首关于春天的诗")
    .stream()                                 // ← 执行流式调用
    .content();                               // ← 获取流式结果

3. 多模型协作

在实际开发场景,在同一个 Spring AI 应用中,一般都会对接多种模型,主要因为:

  • 专业化分工:不同模型做擅长的事,比如代码生成用 Anthropic ,创意文案用 GPT-3.5
  • 用户偏好选择:让用户自己选想用的模型,提升体验。
  • A/B 测试:同时调用不同模型、不同配置,对比响应效果(比如回答质量、速度),选出最优方案。
  • 服务容灾备份:某一个模型服务不可用时,自动切换到备用模型,避免应用直接挂掉。

在上面有提到,自动配置的 ChatClient.Builder 在多个 ChatModel 时会有问题,必须先禁用这个自动配置(否则会出现 Bean 冲突):

spring:
  ai:
    chat:
      client:
        enabled: false

此外,还需要删除 ChatClient.Builder 相关调用代码。

3.1 单一模型,多个不同配置

底层用的是同一个类型的模型,但给不同的 ChatClient 配置不同的默认参数(比如系统提示、温度等)。

首先配置上 DeepSeek

spring:
  application:
    name: spring-ai-01
  ai:
    chat:
      client:
        enabled: false
    deepseek:
      #  api-key: ${AI_DASHSCOPE_API_KEY}
      api-key: sk-070aa594deee454389d5ec912398bacb
      base-url: https://api.deepseek.com

配置两个不同的系统提示词的 ChatClient

@Configuration
public class ChatClientConfig {

    @Bean
    public ChatClient deepSeekChatClient001(DeepSeekChatModel deepSeekChatModel) {
        return ChatClient.builder(deepSeekChatModel)
                .defaultSystem("你是一个严谨的事实问答助手,只回答客观事实,不编造内容")
                .build();
    }

    @Bean
    public ChatClient deepSeekChatClient002(DeepSeekChatModel deepSeekChatModel) {
        return ChatClient.builder(deepSeekChatModel)
                .defaultSystem("你是一个富有创意的文案助手,擅长生成有趣、新颖的内容")
                .build();
    }
}

编写测试类:

@SpringBootTest
class DeepSeekTest01Tests {

    @Autowired
    ChatClient deepSeekChatClient001;

    @Autowired
    ChatClient deepSeekChatClient002;

    @Test
    public void deepSeekTest05() {
        String text1 = deepSeekChatClient001.prompt("你是谁?").call().content();
        System.out.println(text1);

        String text2 = deepSeekChatClient002.prompt("你是谁?").call().content();
        System.out.println(text2);
    }
}

可以看到,同一个问题生成了不同的结果返回:
在这里插入图片描述
提示:可以使用 @Qualifier 注解区分,使用时按需注入。

3.2 不同模型

配置 OpenAIDeepSeek

spring:
  application:
    name: spring-ai-01
  ai:
    chat:
      client:
        enabled: false
    deepseek:
      #  api-key: ${AI_DASHSCOPE_API_KEY}
      api-key: sk-070aa594deee454389d5ec912398bacb
      base-url: https://api.deepseek.com
    openai:
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      api-key: sk-2001b9ae760b4be1944d52c5457f078a

为不同类型的模型分别创建 ChatClient

public class ChatClientConfig {

    // 1. 创建 OpenAI 对应的 ChatClient Bean,名称为 openAiChatClient
    @Bean
    public ChatClient openAiChatClient(OpenAiChatModel openAichatModel) {
        return ChatClient.builder(openAichatModel)
                .build();
    }

    // 2. 创建 DeepSeek 对应的 ChatClient Bean,名称为 deepSeekChatClient
    public ChatClient deepSeekChatClient(DeepSeekChatModel deepSeekChatModel) {
        return ChatClient.builder(deepSeekChatModel)
                .build();
    }

}

3.3 多个兼容 OpenAI 的模型

很多平台(如 GroqAzure OpenAI)都兼容 OpenAIAPI 格式,因此可以复用 OpenAiApi/OpenAiChatModel 类,通过 mutate() 方法创建不同配置的实例。适用于需要使用多个兼容 OpenAIAPI 场景。

官方示例:

@Service
public class MultiModelService {

    private static final Logger logger = LoggerFactory.getLogger(MultiModelService.class);

    @Autowired
    private OpenAiChatModel baseChatModel;

    @Autowired
    private OpenAiApi baseOpenAiApi;

    public void multiClientFlow() {
        try {
            // Derive a new OpenAiApi for Groq (Llama3)
            OpenAiApi groqApi = baseOpenAiApi.mutate()
                .baseUrl("https://api.groq.com/openai")
                .apiKey(System.getenv("GROQ_API_KEY"))
                .build();

            // Derive a new OpenAiApi for OpenAI GPT-4
            OpenAiApi gpt4Api = baseOpenAiApi.mutate()
                .baseUrl("https://api.openai.com")
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

            // Derive a new OpenAiChatModel for Groq
            OpenAiChatModel groqModel = baseChatModel.mutate()
                .openAiApi(groqApi)
                .defaultOptions(OpenAiChatOptions.builder().model("llama3-70b-8192").temperature(0.5).build())
                .build();

            // Derive a new OpenAiChatModel for GPT-4
            OpenAiChatModel gpt4Model = baseChatModel.mutate()
                .openAiApi(gpt4Api)
                .defaultOptions(OpenAiChatOptions.builder().model("gpt-4").temperature(0.7).build())
                .build();

            // Simple prompt for both models
            String prompt = "What is the capital of France?";

            String groqResponse = ChatClient.builder(groqModel).build().prompt(prompt).call().content();
            String gpt4Response = ChatClient.builder(gpt4Model).build().prompt(prompt).call().content();

            logger.info("Groq (Llama3) response: {}", groqResponse);
            logger.info("OpenAI GPT-4 response: {}", gpt4Response);
        }
        catch (Exception e) {
            logger.error("Error in multi-client flow", e);
        }
    }
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐