【SpringAIAlibaba新手村系列】(3)ChatModel 与 ChatClient 的深度对比

简介: 本章深度解析 Spring AI 中 `ChatModel`(底层接口)与 `ChatClient`(高级封装)的本质区别:前者如“手动挡”,精准控制但需写大量样板代码;后者似“智能点餐机”,链式调用、支持系统提示、模板、工具调用等,开发高效。初学者推荐优先使用 `ChatClient`。

第三章 ChatModel 与 ChatClient 的深度对比

s01 > s02 > [ s03 ] s04 > s05 > s06 > s07 > s08 > s09 > s10 > s11 > s12 > s13 > s14 > s15 > s16 > s17 > s18

"底层看 ChatModel, 开发多用 ChatClient" -- 一个偏原始能力, 一个偏工程效率。


一、为什么需要两个 API?

1.1 初学者的困惑

很多初学者看到 Spring AI 同时提供了 ChatModelChatClient 都会问:

  • "这两个不都是用来调用 AI 的吗?"
  • "到底该用哪一个?"
  • "他们有什么区别?"

这一章我们就来彻底搞清楚这个问题!

1.2 比喻理解

让我用一个生活化的比喻来解释:

ChatModel(对话模型) 就相当于手机的「原始电话功能」

  • 只能打电话(调用 send/receive)
  • 功能简单直接
  • 需要自己处理各种细节

ChatClient(对话客户端) 相当于「智能手机」

  • 在电话基础上,增加了:
    • 通讯录管理(系统提示词)
    • 短信应用(Prompt 模板)
    • 语音助手(工具调用)
    • 智能外设(向量存储、记忆功能)
  • 功能更丰富,使用更便捷

二、ChatModel 详解

2.1 什么是 ChatModel?

ChatModel 是 Spring AI 的核心底层接口,它直接封装了与 AI 模型的通信。

大白话解释:把 ChatModel 想象成"AI 模型的翻译官",你给它发中文,它能听懂;AI 返回的内容,它也能翻译成 Java 对象给你。

public interface ChatModel extends Model, ChatOptionsDesktop {
   
    // 核心方法就两个:

    // 方法1:一次性返回完整结果
    ChatResponse call(Prompt prompt);

    // 方法2:流式返回(一个字一个字吐出来)
    Flux<ChatResponse> 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 什么是 ChatClient?

ChatClient 是构建在 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 功能对比表

特性 ChatModel ChatClient
层级 底层接口 高级封装
API 风格 直接调用 链式 Builder
系统提示词 需手动构造 Prompt 对象 .system() 方法直接设置
模板变量 不支持 支持 .param() 替换占位符
结构化输出 需额外配置 .entity() 方法直接映射
对话记忆 不支持 支持 Advisor 扩展
工具调用 需手动配置 支持 .tools() 方法
适用场景 需要精确控制的底层开发 快速构建 AI 功能

4.2 如何选择?

使用 ChatModel 的场景

  1. 你需要精确控制请求的每个参数
  2. 你是库/框架开发者,需要底层能力
  3. 你需要实现自定义的 AI 逻辑

使用 ChatClient 的场景

  1. 日常的 AI 对话开发(推荐)
  2. 需要快速构建原型
  3. 需要用到系统提示词、模板、工具调用等高级功能

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("什么是反射?");

// 第三步:组合成对话消息列表
List<Message> 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();

从上面的对比可以看出:

  • ChatClient:3 行代码搞定(链式调用)
  • 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.java

5.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 Flux<String> 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 高级封装,提供链式调用的便捷API
@Bean Spring 中用于注册组件的注解
链式调用 通过 Builder 模式实现的方法链

7.2 选择建议

┌─────────────────────────────────────────────────┐
│                  选择决策树                       │
│                                                  │
│  需要精细控制底层请求? ──YES──→ 使用 ChatModel   │
│         │                                       │
│         NO                                      │
│         ↓                                       │
│  直接开发AI应用功能? ──YES──→ 使用 ChatClient   │
│                                                  │
└─────────────────────────────────────────────────┘

本章重点

  1. 理解 ChatModel 与 ChatClient 的定位差异
  2. 掌握 ChatClient 的链式调用写法
  3. 能够根据场景选择合适的 API

下章剧透(s04):

了解了两种 API 的使用后,下一章我们将学习流式输出的高级用法,体验"打字机"效果的实现原理。


📝 编辑者:Flittly
📅 更新时间:2026年3月
🔗 相关资源Spring AI ChatClient 官方文档

目录
相关文章
|
6天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
10863 75
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
6天前
|
人工智能 IDE API
2026年国内 Codex 安装教程和使用教程:GPT-5.4 完整指南
Codex已进化为AI编程智能体,不仅能补全代码,更能理解项目、自动重构、执行任务。本文详解国内安装、GPT-5.4接入、cc-switch中转配置及实战开发流程,助你从零掌握“描述需求→AI实现”的新一代工程范式。(239字)
3774 129
|
1天前
|
人工智能 Kubernetes 供应链
深度解析:LiteLLM 供应链投毒事件——TeamPCP 三阶段后门全链路分析
阿里云云安全中心和云防火墙已在第一时间上线相关检测与拦截策略!
1306 5
|
2天前
|
人工智能 自然语言处理 供应链
【最新】阿里云ClawHub Skill扫描:3万个AI Agent技能中的安全度量
阿里云扫描3万+AI Skill,发现AI检测引擎可识别80%+威胁,远高于传统引擎。
1250 2
|
12天前
|
人工智能 JavaScript API
解放双手!OpenClaw Agent Browser全攻略(阿里云+本地部署+免费API+网页自动化场景落地)
“让AI聊聊天、写代码不难,难的是让它自己打开网页、填表单、查数据”——2026年,无数OpenClaw用户被这个痛点困扰。参考文章直击核心:当AI只能“纸上谈兵”,无法实际操控浏览器,就永远成不了真正的“数字员工”。而Agent Browser技能的出现,彻底打破了这一壁垒——它给OpenClaw装上“上网的手和眼睛”,让AI能像真人一样打开网页、点击按钮、填写表单、提取数据,24小时不间断完成网页自动化任务。
2655 6

热门文章

最新文章