一、ChatModel和ChatClient
- ChatModel :底层模型交互层,只负责和大模型通信,纯原始 API 封装,无会话、无工具、无记忆、无便捷构建器。
- ChatClient :上层应用门面封装,基于 ChatModel 构建,提供流式 / 同步、记忆、工具调用、Prompt 模板、会话管理、链式调用等业务能力,开发更简单。
Chat Model
ChatModel API 让应用开发者可以非常方便的与 AI 模型进行文本交互,它抽象了应用与模型交互的过程,包括使用 Prompt 作为输入,使用 ChatResponse 作为输出等。ChatModel 的工作原理是接收 Prompt 或部分对话作为输入,将输入发送给后端大模型,模型根据其训练数据和对自然语言的理解生成对话响应,应用程序可以将响应呈现给用户或用于进一步处理。

ChatModel文档地址:对话模型(Chat Model)-阿里云Spring AI Alibaba官网官网
ChatClient
ChatClient 提供了与 AI 模型通信的 Fluent API,它支持同步和反应式(Reactive)编程模型。与 ChatModel、Message、ChatMemory 等原子 API 相比,使用 ChatClient 可以将与 LLM 及其他组件交互的复杂性隐藏在背后,因为基于 LLM 的应用程序通常要多个组件协同工作(例如,提示词模板、聊天记忆、LLM Model、输出解析器、RAG 组件:嵌入模型和存储),并且通常涉及多个交互,因此协调它们会让编码变得繁琐。当然使用 ChatModel 等原子 API 可以为应用程序带来更多的灵活性,成本就是您需要编写大量样板代码。
ChatClient 类似于应用程序开发中的服务层,它为应用程序直接提供 AI 服务,开发者可以使用 ChatClient Fluent API 快速完成一整套 AI 交互流程的组装。
包括一些基础功能,如:
- 定制和组装模型的输入(Prompt)
- 格式化解析模型的输出(Structured Output)
- 调整模型交互参数(ChatOptions)
还支持更多高级功能:
- 聊天记忆(Chat Memory)
- 工具/函数调用(Function Calling)
- RAG
ChatClient 文档地址:Chat Client-阿里云Spring AI Alibaba官网官网
二、分层关系
业务代码 → ChatClient(上层门面)
↓ 内部持有
ChatModel(底层模型驱动)
↓
大模型API(OpenAI/通义千问/DeepSeek等)
ChatClient 依赖 ChatModel,ChatModel 可以单独脱离 ChatClient 使用。
三、详细对比
1. 定位与职责
ChatModel
- 底层原始接口,对应厂商原生对话接口
- 仅处理:发送消息列表
List<Message>→ 返回ChatResponse - 只做请求组装、网络调用、响应解析
- 不封装会话、记忆、工具、prompt 优化、流式便捷 API
- 每个大模型对应一个实现:
OpenAiChatModel、DashScopeChatModel、QwenChatModel
ChatClient
- 面向开发者的高层工具类,包装 ChatModel
- 一站式封装对话全流程:
- 同步 / 流式输出统一 API
- 内置聊天记忆(Memory)
- 工具函数调用(Function Calling)
- Prompt 模板、变量替换
- 构建器链式调用
ChatClient.create().prompt().user("xxx").call() - 会话上下文简化管理
- 不绑定具体模型,传入任意 ChatModel 即可切换大模型
2. 使用代码对比(Spring AI)
① 直接用 ChatModel(底层写法,繁琐)
java
// 1. 初始化底层模型
ChatModel chatModel = new DashScopeChatModel(...);
// 2. 手动拼接消息
List<Message> messages = List.of(
new UserMessage("介绍Spring AI")
);
// 3. 手动构建请求、调用、提取结果
ChatResponse response = chatModel.call(new Prompt(messages));
String content = response.getResult().getOutput().getText();
缺点:每次手动拼消息、流式要自己处理 Stream、记忆 / 工具需要自己实现。
② 使用 ChatClient(推荐业务写法)
java
// 1. 传入ChatModel构建客户端
ChatClient chatClient = ChatClient.create(chatModel);
// 2. 链式极简调用,内置封装
String res = chatClient.prompt()
.user("介绍Spring AI")
.call()
.content();
// 流式输出
Flux<String> stream = chatClient.prompt()
.user("长篇故事")
.stream()
.content();
自带记忆、工具、模板,代码量大幅减少。
3. 核心能力差异表
| 能力 | ChatModel | ChatClient |
|---|---|---|
| 底层模型通信 | ✅ 核心能力 | ❌ 内部委托 ChatModel |
| 链式 Prompt 构建 | ❌ 无 | ✅ 完整 Builder |
| 流式输出简化 API | ❌ 原生底层流,需手动处理 | ✅ 统一 stream () 方法 |
| 聊天记忆(Memory) | ❌ 需手动维护消息列表 | ✅ 内置支持,自动追加历史 |
| Function Calling 工具调用 | ❌ 手动组装工具参数 | ✅ 简单注册工具即可自动调度 |
| Prompt 模板变量渲染 | ❌ 无封装 | ✅ .promptTemplate () 直接传参 |
| 多轮会话简化 | ❌ 手动拼接历史 Message | ✅ 自动管理上下文 |
| 业务友好 API | ❌ 原始底层 | ✅ 面向业务开发 |
四、LangChain4j 同名
ChatLanguageModel= SpringAIChatModel:底层模型客户端AiServices/ChatClient(LangChain4j 新版)= SpringAIChatClient:高层封装,提供记忆、工具、代理、接口封装
五、开发选型建议
- 底层自定义框架、精细控制请求参数:用 ChatModel
- 业务开发、快速搭建对话机器人、RAG、工具 Agent:优先 ChatClient
- 二者关系:ChatClient 是对 ChatModel 的增强封装,不会替代 ChatModel,底层通信依然依赖 ChatModel。
六、Spring AI Alibaba ChatModel 与 ChatClient 核心区别
基于 spring-ai-alibaba-starter(通义千问 DashScope)完整区分,底层依赖 Spring AI 原生规范,Alibaba 只是实现 DashScope 厂商模型。
(一)层级依赖关系
业务代码
↓
ChatClient(上层门面、工具集、业务封装)
内部持有 ChatModel
↓
DashScopeChatModel(ChatModel 实现类,底层通信裸接口)
↓
DashScope OpenAPI(阿里云通义千问接口)
ChatClient必须依赖 ChatModel 才能工作;ChatModel可独立使用,不需要 ChatClient。
(二)两者定位本质
1. DashScopeChatModel(实现 ChatModel 接口)
底层裸通信层 只负责一件事:拼装 Prompt、调用 DashScope HTTP 接口、解析原始返回体。 无任何上层能力,所有上下文、工具、记忆、模板都要自己手写。
2. ChatClient(Spring AI 通用高层封装,Alibaba 复用)
业务开发工具门面 对 ChatModel 做全套增强封装:链式构建、记忆、工具调用、Prompt 模板、流式简化、结构化输出、会话管理。 不绑定阿里云,切换 DeepSeek、OpenAI 只需替换内部 ChatModel。
(三)代码对比:纯 DashScopeChatModel 底层写法
1. 配置 Bean
java
@Bean
public DashScopeChatModel dashScopeChatModel(DashScopeProperties properties) {
return new DashScopeChatModel(properties);
}
2. 原始调用(繁琐)
java
@Autowired
private DashScopeChatModel chatModel;
public String chatByModel() {
// 1. 手动组装消息
List<Message> messages = List.of(
new SystemMessage("你是专业Java助手"),
new UserMessage("解释Spring AI Alibaba")
);
Prompt prompt = new Prompt(messages);
// 2. 原始调用接口
ChatResponse response = chatModel.call(prompt);
// 3. 手动提取文本
return response.getResult().getOutput().getText();
}
缺点
- 多轮对话:必须自己缓存历史消息,每次手动拼接
messages; - 工具调用:手动拼装 ToolDefinition、解析工具返回、二次请求;
- 流式输出:调用
stream()返回 Flux<ChatResponse>,自己循环取内容; - 无变量模板,字符串拼接 Prompt 极易出错;
- 没有统一简化 API,每个场景都要重复样板代码。
(四)代码对比:ChatClient 高层写法(推荐业务用)
ChatClient 基于上面同一个 DashScopeChatModel 构建:
java
@Bean
public ChatClient chatClient(DashScopeChatModel dashScopeChatModel) {
return ChatClient.builder(dashScopeChatModel)
.defaultSystem("你是专业Java开发专家") // 全局系统提示
.build();
}
1. 普通对话极简调用
java
@Autowired
private ChatClient chatClient;
public String chatByClient() {
return chatClient.prompt()
.user("解释Spring AI Alibaba")
.call()
.content();
}
2. 内置高阶能力(ChatModel 原生不提供)
① Prompt 变量模板
String res = chatClient.prompt()
.user("用{lang}解释{tech}")
.param("lang", "中文")
.param("tech", "Spring AI Alibaba ChatClient")
.call()
.content();
② 流式输出一行 API
java
Flux<String> stream = chatClient.prompt()
.user("写一篇长文介绍大模型")
.stream()
.content();
③ 聊天记忆自动维护(多轮对话不用手动存消息)
java
// 绑定内存记忆,自动追加历史上下文
ChatClient memoryClient = ChatClient.builder(dashScopeChatModel)
.defaultSystem("你是聊天助手")
.build()
.mutate()
.chatMemory(InMemoryChatMemory.create())
.build();
memoryClient.prompt().user("我的名字是张三").call();
// 无需手动拼接历史,模型自动记住名字
memoryClient.prompt().user("我叫什么?").call();
④ 工具函数调用(一行注册,自动调度)
java
// 注册自定义工具
String res = chatClient.prompt()
.tools(new WeatherTool())
.user("北京今天天气")
.call()
.content();
(五)Spring AI Alibaba 场景下能力对比表
| 能力点 | DashScopeChatModel(ChatModel) | ChatClient |
|---|---|---|
| 阿里云通义千问接口通信 | ✅ 核心底层能力 | ❌ 委托内部 ChatModel 执行 |
| 链式 Builder 构建 prompt | ❌ 无,手动 List<Message> | ✅ .prompt().user().param() |
| Prompt 变量模板渲染 | ❌ 自己字符串拼接 | ✅ 内置 param 模板 |
| 极简流式 content () | ❌ 原始 Flux<ChatResponse> | ✅ .stream().content() |
| 内置 ChatMemory 多轮记忆 | ❌ 需手动维护消息列表 | ✅ 一行绑定记忆 |
| 简化 Function Calling 工具 | ❌ 手动组装工具定义、二次请求 | ✅ 直接注册 tools () 自动处理 |
| 全局默认 System 提示词 | ❌ 每次调用手动加 SystemMessage | ✅ Bean 构建时统一配置 |
| 结构化输出(POJO 解析) | ❌ 手动 JSON 转对象 | ✅ .entity(Class<T>) 自动映射 |
| 厂商无关切换模型 | 绑定 DashScope 实现 | 替换内部 ChatModel 即可无缝切换 |
(六)使用场景选型
-
选用 DashScopeChatModel(ChatModel)
- 需要精细控制 DashScope 原生请求参数(top_p、temperature、seed、输入图片、多模态参数);
- 自研上层对话框架,自己封装记忆 / 工具;
- 只做单次简单调用,不需要多轮、工具、模板。
-
选用 ChatClient(业务首选)
- 对话机器人、RAG、Agent、多轮聊天;
- 需要工具调用、会话记忆、Prompt 模板;
- 希望代码简洁,减少重复样板代码;
- 未来可能切换其他大模型(DeepSeek、OpenAI 等)。