典型回答#
在 Spring AI 框架中,ChatModel 和 ChatClient 是构建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 中的 Connection 或 Statement,或者 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();
|