典型回答

在 Spring AI 框架中,ChatModelChatClient 是构建LLM应用的两个核心抽象概念,它们分别代表了底层驱动能力高层应用编排

  • **ChatModel**引擎:负责直接与 AI 模型提供商(如 OpenAI、Azure、本地模型)通信,处理底层的请求和响应。
  • **ChatClient**驾驶舱/控制台:建立在 ChatModel 之上,为开发者提供流畅的 API(Fluent API),用于编排对话流、管理上下文、调用工具(Function Calling)以及处理响应转换。

ChatModel是 Spring AI 的核心API,直接对接具体的 LLM 提供商,如有具体的实现: OpenAiChatModel, AzureAiChatModel,负责将 Spring AI 统一的 ChatRequest 转换为特定厂商的 API 请求格式。负责接收厂商的原始响应并转换为统一的 ChatResponse

他就像 JDBC 中的 ConnectionStatement,或者 HTTP 客户端中的 RestTemplate/WebClient 底层执行器。它只管“发出去”和“收回来”,不管业务逻辑怎么串。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@Autowired
private ChatModel chatModel; // 注入具体的实现 OpenAiChatModel

public String getWeather(String city) {
    // 1. 手动构建消息列表
    List<Message> messages = new ArrayList<>();
    messages.add(new UserMessage("今天 " + city + " 的天气怎么样?"));
    
    // 2. 构建请求
    ChatRequest request = ChatRequest.builder()
            .messages(messages)
            .build();

    // 3. 调用底层模型
    ChatResponse response = chatModel.call(request);

    // 4. 手动解析响应内容
    return response.getResult().getOutput().getText();
}

ChatClient 是基于 ChatModel 构建的高级抽象,旨在简化应用开发。提供 .prompt(), .system(), .user(), .call() 等链式调用方法。好包括:

- **记忆管理**:内置对 `ChatMemory`(对话记忆)的支持,自动处理多轮对话的历史记录。
- **工具调用 (Function Calling)**:极其便捷地注册和绑定 Java 方法作为 AI 的工具(Tools),自动处理参数提取和方法 invocation。
- **结构化输出**:支持直接将响应转换为 POJO (Java 对象)、String 或 Flux (流式响应),无需手动解析 JSON。
- **观察性 (Observability)**:内置对 Micrometer Tracing 的支持,方便监控链路。
- **扩展机制(Advisor)**:可以用于拦截、修改和增强 Spring 应用中的 AI 交互功能,那就是Advisor,通过利用Advisor,开发者可以创建更复杂、可重用且易于维护的 AI 组件。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Autowired
private ChatClient chatClient; // 通常通过 ChatClient.builder(chatModel).build() 创建

// 场景1简单对话 + 自动转对象
public WeatherInfo getWeatherInfo(String city) {
    return chatClient.prompt()
            .user("查询 " + city + " 的天气")
            .call()
            .entity(WeatherInfo.class); // 自动将 JSON 转为 Java 对象
}

// 场景2带工具调用 (Function Calling)
public String chatWithTools(String input) {
    return chatClient.prompt()
            .tools(weatherService::getWeather) // 一键绑定 Java 方法为工具
            .user(input)
            .call()
            .content();
}

// 场景3带上下文记忆
public String chatWithMemory(String sessionId, String input) {
    return chatClient.prompt()
            .advisors(a -> a.param("chatMemoryId", sessionId)) // 自动加载/保存历史
            .user(input)
            .call()
            .content();
}

ChatClient 内部持有一个 ChatModel 实例。当你调用 chatClient.call() 时,它最终会委托给内部的 chatModel.call() 去执行真正的网络请求。通常你先从 Spring 容器中获取一个配置好的 ChatModel Bean(例如 openAiChatModel),然后利用它来构建 ChatClient

1
2
3
ChatClient client = ChatClient.builder(chatModel)
                              .defaultAdvisors(...) // 配置默认的记忆或拦截器
                              .build();