【SpringAIAlibaba新手村系列】(3)ChatModel 与 ChatClient 的深度对比
第三章 ChatModel 与 ChatClient 的深度对比s01 s02 [ s03 ] s04 s05 s06 s07 s08 s09 s10 s11 s12 s13 s14 s15 s16 s17 s18底层看 ChatModel, 开发多用 ChatClient-- 一个偏原始能力, 一个偏工程效率。一、为什么需要两个 API1.1 初学者的困惑很多初学者看到 Spring AI 同时提供了ChatModel和ChatClient都会问这两个不都是用来调用 AI 的吗到底该用哪一个他们有什么区别这一章我们就来彻底搞清楚这个问题1.2 比喻理解让我用一个生活化的比喻来解释ChatModel对话模型 就相当于手机的「原始电话功能」只能打电话调用 send/receive功能简单直接需要自己处理各种细节ChatClient对话客户端 相当于「智能手机」在电话基础上增加了通讯录管理系统提示词短信应用Prompt 模板语音助手工具调用智能外设向量存储、记忆功能功能更丰富使用更便捷二、ChatModel 详解2.1 什么是 ChatModelChatModel是 Spring AI 的核心底层接口它直接封装了与 AI 模型的通信。大白话解释把ChatModel想象成AI 模型的翻译官你给它发中文它能听懂AI 返回的内容它也能翻译成 Java 对象给你。public interface ChatModel extends Model, ChatOptionsDesktop { // 核心方法就两个 // 方法1一次性返回完整结果 ChatResponse call(Prompt prompt); // 方法2流式返回一个字一个字吐出来 FluxChatResponse stream(Prompt prompt); }2.2 ChatModel 的特点特点说明底层接口直接与 AI 服务商通信功能单一只负责发送消息、接收回复灵活度高可以精确控制请求的每个细节使用难度需要了解 Prompt、Message 等概念2.3 代码示例// 使用 ChatModel 调用 AI RestController public class ChatModelController { Resource private ChatModel chatModel; GetMapping(/chatmodel/hello) public String hello(String msg) { // ChatModel 的调用方式直接传入字符串 String result chatModel.call(msg); return result; } }三、ChatClient 详解3.1 什么是 ChatClientChatClient是构建在ChatModel之上的高级 API它提供了链式调用Builder模式的便捷写法。大白话解释ChatClient就像一个智能点餐机不仅能帮你叫外卖还支持定义口味偏好系统提示词选择优惠券模板变量凑单推荐RAG 检索会员积分对话记忆3.2 ChatClient 的链式调用// ChatClient 的经典使用方式链式调用 String result chatClient.prompt() // 第一步创建提示词 .system(你是一个Java助手) // 第二步设置系统提示词 .user(什么是反射) // 第三步设置用户问题 .call() // 第四步执行调用 .content(); // 第五步获取结果这种链式写法比原生ChatModel更加直观易读。3.3 代码示例// 使用 ChatClient 调用 AI RestController public class ChatClientController { // 注意ChatClient 不能直接注入需要通过 Builder 构建 private final ChatClient dashScopeChatClient; // 构造函数注入并构建 ChatClient public ChatClientController(ChatModel dashScopeChatModel) { // 通过 ChatModel 创建 ChatClient this.dashScopeChatClient ChatClient.builder(dashScopeChatModel).build(); } GetMapping(/chatclient/hello) public String hello(String msg) { // 链式调用语义清晰 String result dashScopeChatClient.prompt() .user(msg) // 设置用户消息 .call() // 调用 AI .content(); // 获取文本内容 return result; } }四、两者对比4.1 功能对比表特性ChatModelChatClient层级底层接口高级封装API 风格直接调用链式 Builder系统提示词需手动构造 Prompt 对象.system()方法直接设置模板变量不支持支持.param()替换占位符结构化输出需额外配置.entity()方法直接映射对话记忆不支持支持 Advisor 扩展工具调用需手动配置支持.tools()方法适用场景需要精确控制的底层开发快速构建 AI 功能4.2 如何选择使用 ChatModel 的场景你需要精确控制请求的每个参数你是库/框架开发者需要底层能力你需要实现自定义的 AI 逻辑使用 ChatClient 的场景日常的 AI 对话开发推荐需要快速构建原型需要用到系统提示词、模板、工具调用等高级功能4.3 ChatModel 也能实现 ChatClient 的功能但代码更多很多初学者误以为 ChatModel 功能太简单做不到 ChatClient 的那些高级功能。其实ChatModel 通过手写样板代码完全可以实现相同的功能只不过代码量会多一些。让我们对比一下两者的实现方式场景让 AI 扮演 Java 助手回答技术问题ChatClient 的写法简洁String result chatClient.prompt() .system(你是一个专业的Java工程师) // 系统提示词 .user(什么是反射) // 用户问题 .call() .content();ChatModel 的写法样板代码多// ChatModel 需要手动构造 Prompt 对象 // 第一步创建系统消息 SystemPromptTemplate systemPromptTemplate new SystemPromptTemplate( 你是一个专业的%s, Java工程师 // 模板变量 ); Message systemMessage systemPromptTemplate.createMessage( Map.of(role, professional, specialty, Java工程师) ); // 第二步创建用户消息 UserMessage userMessage new UserMessage(什么是反射); // 第三步组合成对话消息列表 ListMessage messages new ArrayList(); messages.add(systemMessage); messages.add(userMessage); // 第四步创建 Prompt 对象 Prompt prompt new Prompt(messages); // 第五步调用并获取结果 ChatResponse response chatModel.call(prompt); String result response.getResult().getOutput().getText();从上面的对比可以看出ChatClient3 行代码搞定链式调用ChatModel需要 10 行样板代码手动构造那 ChatModel 还有什么用虽然 ChatModel 代码多但它给了你最大的控制权可以自定义消息类型可以精确控制每个参数可以在发送前对消息进行任意处理总结ChatModel 就像 手动挡汽车功能全但需要自己换挡ChatClient 像 自动挡汽车开起来简单但牺牲了一些灵活性。初学者建议90% 的情况下使用ChatClient就够了。除非你有特殊需求否则不需要直接使用ChatModel。五、项目代码详解5.1 项目结构SAA-03ChatModelChatClient/ ├── pom.xml # 依赖配置 ├── src/main/java/com/atguigu/study/ │ ├── config/ │ │ └── SaaLLMConfig.java # 配置文件 │ ├── controller/ │ │ ├── ChatClientController.java # ChatClient 示例 │ │ ├── ChatClientControllerV2.java # ChatClient V2写法 │ │ └── ChatModelController.java # ChatModel 示例 │ └── Saa03ChatModelChatClientApplication.java5.2 配置类package com.atguigu.study.config; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.model.ChatModel; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 配置类注册多个 ChatModel 和 ChatClient 的 Bean */ Configuration public class SaaLLMConfig { /** * 创建一个命名的 ChatModel阿里云 DashScope * Bean 注解会将方法返回值注册为 Spring 容器中的 Bean * 默认名称是方法名这里我们显式命名为 dashScopeChatModel */ Bean(dashScopeChatModel) public ChatModel dashScopeChatModel() { // 这里不需要手动创建Spring AI 的自动配置会处理 // 只是为了演示多Bean的情况保留这个方法作为标记 return null; // 实际由 Spring AI 自动配置注入 } /** * 创建一个命名的 ChatClient基于 dashScopeChatModel * 名称为 dashScopeChatClient */ Bean(dashScopeChatClient) public ChatClient dashScopeChatClient(ChatModel dashScopeChatModel) { // 通过 Builder 模式创建 ChatClient return ChatClient.builder(dashScopeChatModel).build(); } }提示实际上这些配置大部分由 Spring AI 的自动配置Auto Configuration完成了我们只需要了解原理即可。5.3 ChatClientController V2 写法推荐package com.atguigu.study.controller; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.model.ChatModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * 使用 Autowired 注入 ChatClient */ RestController public class ChatClientControllerV2 { // 直接注入已注册的 ChatClient Bean Autowired private ChatClient chatClient; GetMapping(/chatclientv2/dochat) public String doChat(RequestParam(name msg, defaultValue 2加9等于几) String msg) { // 简洁的链式调用 return chatClient.prompt() .user(msg) // 设置用户消息 .call() // 调用 .content(); // 获取文本内容 } }六、进阶ChatClient 的多种用法6.1 返回 Flux 流式响应GetMapping(/stream) public FluxString stream(String msg) { return chatClient.prompt() .user(msg) .stream() // 开启流式模式 .content(); }6.2 方法引用写法// 更加简洁的 Lambda 写法 GetMapping(/chat) public String chat(String msg) { return chatClient.prompt(msg).call().content(); } // 或者更复杂点 return chatClient.prompt() .system(你是一个专业的%s, Java工程师) // 格式化 .user(msg) .call() .chatResponse() → 获取 AI 返回来的【完整响应对象】头体脚 .getResult() → 拿到【结果体】 .getOutput() → 拿到【输出内容】 .getText() → 拿到【文本字符串】七、本章小结7.1 核心知识点概念说明ChatModel底层AI调用接口直接与模型通信ChatClient高级封装提供链式调用的便捷APIBeanSpring 中用于注册组件的注解链式调用通过 Builder 模式实现的方法链7.2 选择建议┌─────────────────────────────────────────────────┐ │ 选择决策树 │ │ │ │ 需要精细控制底层请求 ──YES──→ 使用 ChatModel │ │ │ │ │ NO │ │ ↓ │ │ 直接开发AI应用功能 ──YES──→ 使用 ChatClient │ │ │ └─────────────────────────────────────────────────┘本章重点理解 ChatModel 与 ChatClient 的定位差异掌握 ChatClient 的链式调用写法能够根据场景选择合适的 API下章剧透s04了解了两种 API 的使用后下一章我们将学习流式输出的高级用法体验打字机效果的实现原理。编辑者Flittly更新时间2026年3月相关资源Spring AI ChatClient 官方文档