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

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

第三章 ChatModel 与 ChatClient 的深度对比

版本标注

  • Spring AI: 1.1.2
  • Spring AI Alibaba: 1.1.2.0

章节定位

  • ChatModelChatClient 依然是最重要的基础抽象。
  • 但在 Spring AI Alibaba 1.1.2.x 中,它们往往作为 ReactAgent、Workflow、Graph 节点内部的基础能力来使用,而不是最终应用层的最高抽象。

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
 */
@Configuration
public class SaaLLMConfig
{
   
    /**
     * 创建一个命名的 ChatClient(基于 dashScopeChatModel)
     * 名称为 "dashScopeChatClient"
     */
    @Bean("dashScopeChatClient")
    public ChatClient dashScopeChatClient(ChatModel dashScopeChatModel)
    {
   
        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();
}

// 或者更复杂点
ChatResponse response = chatClient.prompt()
    .system("你是一个专业的%s", "Java工程师")
    .user(msg)
    .call()
    .chatResponse();

String result = response.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 官方文档

目录
相关文章
|
2月前
|
人工智能 前端开发 Java
【SpringAIAlibaba新手村系列】(4)流式输出与响应式编程
本文围绕 Spring AI 中的流式输出与响应式编程展开,重点解释了传统一次性响应与流式返回的差异,以及 Flux 在异步数据流中的核心作用。文章结合 ChatModel.stream() 与 ChatClient 的多种代码示例,说明如何实现 AI 内容的边生成边返回,并帮助读者理解流式调用在用户体验、性能和长文本场景中的实际价值。
822 4
【SpringAIAlibaba新手村系列】(4)流式输出与响应式编程
|
人工智能 JavaScript Java
【SpringAIAlibaba新手村系列】(1)初识 Spring AI Alibaba 框架
本文介绍了SpringAIAlibaba框架的基本概念和使用方法。作为Spring官方AI框架的阿里云实现版本,它简化了Java开发者调用AI模型的过程。文章详细讲解了核心概念如ChatModel、ChatClient,以及阿里云百炼平台的功能。通过HelloWorld项目示例,展示了如何配置APIKey、编写控制层代码,实现普通调用和流式输出两种AI交互方式。重点阐述了SpringAI与SpringAIAlibaba的关系,以及自动配置机制的工作原理,帮助开发者快速上手这一框架。
3529 4
|
1月前
|
人工智能 Java API
【SpringAIAlibaba新手村系列】(2)Ollama 本地大模型调用
本章详解如何用Spring AI接入Ollama本地大模型:解决远程调用的联网依赖、隐私泄露与费用问题;支持Qwen、Llama等开源模型,零成本、低延迟、全离线运行;重点掌握`@Qualifier`多模型注入、流式响应(Flux)及本地API(`http://localhost:11434`)集成。
659 5
|
1月前
|
人工智能 Java API
【SpringAIAlibaba新手村系列】(5)Prompt 提示词基础与多种消息类型
本章详解Spring AI 1.1.2中Prompt核心机制:以System/User/Assistant/Tool四类消息构建结构化提示,强调“角色决定语义”;涵盖多模型配置、链式API与底层Message组装两种实践方式,并给出系统消息设计最佳实践。
554 7
|
1月前
|
人工智能 JSON Java
【SpringAIAlibaba新手村系列】(6)PromptTemplate 提示词模板与变量替换
本章详解Spring AI的PromptTemplate提示词模板机制,涵盖变量替换、系统消息模板(SystemPromptTemplate)、外部文件加载等核心功能,助力实现提示词参数化、复用与动态组装,提升RAG、Agent及结构化输出场景下的开发效率与可维护性。
289 6
|
1月前
|
人工智能 JSON Java
【SpringAIAlibaba新手村系列】(7)结构化输出与对象映射
本文详解 Spring AI 结构化输出功能,通过 Java Record 与 .entity() 方法,实现 AI 的 JSON 响应自动映射为 Java 对象,解决纯文本难以集成的问题。文中还对比了 Lambda 写法并提供 Prompt 设计最佳实践。
333 4
|
1月前
|
NoSQL Java 数据库
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
本文围绕 Embedding 与向量数据库展开,讲解了文本向量化、相似度检索和 VectorStore 的基本用法,并结合 SimpleVectorStore 示例说明了 Spring 中自动装配与手动注册 Bean 的区别,为后续学习 RAG 打下基础。
572 5
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
|
人工智能 NoSQL Java
【SpringAIAlibaba新手村系列】(8)持久化会话与 Redis 内存管理
本文详解 Spring AI 的会话记忆机制,从内存版 MemorySaver 到 Redis 版 RedisSaver,实现 AI 对话的上下文连续性。文章以 ReactAgent 为核心,讲解如何通过 threadId 管理会话线程,并将 Agent 状态持久化到 Redis 中。
650 4
|
2月前
|
人工智能 自然语言处理 Java
大模型应用开发5-SpringAIalibaba实战
本文介绍了SpringAIAlibaba开源项目,该项目基于SpringAI构建,为阿里云通义系列模型提供Java开发实践。主要内容包括: 基础使用:配置模型API、依赖引入、调用示例,支持同步和流式调用; 多种集成方式:对接本地Ollama模型、ChatClient高级API、SSE流式输出; 核心功能实现:提示词模板、结构化输出、持久化内存、文本生成图片/语音; 高级能力:向量数据库、RAG增强检索、工具调用(Tool Calling); MCP协议:标准化工具调用方案,实现服务端工具共享;
|
2月前
|
存储 人工智能 Java
吃透 Spring AI Alibaba 多智能体|四大协同模式+完整代码
本文详细讲解 Spring AI Alibaba Multi-Agent 多智能体架构,包含顺序执行、并行执行、LLM 路由、监督者四大协同模式,搭配可运行代码示例与真实业务场景,从零带你上手多智能体开发。
1329 3

热门文章

最新文章