ChatClient和ChatModel区别解析

目录

一、项目环境与基础配置

[1.1 版本信息](#1.1 版本信息)

[1.2 Maven 核心依赖](#1.2 Maven 核心依赖)

[1.3 应用配置(application.properties)](#1.3 应用配置(application.properties))

二、两种同步调用实现方案

[2.1 方案一:ChatClient 高阶封装写法](#2.1 方案一:ChatClient 高阶封装写法)

[2.2 方案二:ChatModel 底层原生写法](#2.2 方案二:ChatModel 底层原生写法)

[三、ChatClient 与 ChatModel 深度对比](#三、ChatClient 与 ChatModel 深度对比)

[3.1 核心定位](#3.1 核心定位)

[3.2 多维度对比表](#3.2 多维度对比表)

[3.3 适用场景建议](#3.3 适用场景建议)

[四、实战踩坑:getText() 与 getContent() 取值问题解析](#四、实战踩坑:getText() 与 getContent() 取值问题解析)

[4.1 问题现象](#4.1 问题现象)

[4.2 根因分析](#4.2 根因分析)

[4.3 补充:阿里云 OpenAI 兼容模式原理](#4.3 补充:阿里云 OpenAI 兼容模式原理)


在基于 Spring AI 对接大模型的开发过程中,框架提供了 ChatClientChatModel 两套核心调用接口,二者定位、用法、灵活性差异较大,很多开发者容易混淆。

本文结合阿里云通义千问(qwen-max) 实战场景,基于 OpenAI 兼容模式完成接口调用,同时针对开发中遇到的 getText() / getContent() 取值方法不一致的问题进行深度复盘。完整演示两套接口的编码实现、核心区别,并梳理环境配置、踩坑原因与生产最佳实践,帮助大家彻底掌握 Spring AI 基础调用能力。

本文运行环境:Spring Boot 4.0.6 + Spring AI 2.0.0-M8,采用阿里云 DashScope OpenAI 兼容协议,使用 OpenAI 依赖直接调用通义千问模型。

一、项目环境与基础配置

1.1 版本信息

复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.6</version>
    <relativePath/>
</parent>

<properties>
    <java.version>17</java.version>
    <!-- Spring AI 里程碑测试版 -->
    <spring-ai.version>2.0.0-M8</spring-ai.version>
</properties>

1.2 Maven 核心依赖

使用 Spring AI OpenAI 启动器,借助阿里云兼容协议调用通义千问,无需额外引入 DashScope 专属依赖:

复制代码
<dependencies>
    <!-- Spring MVC 基础web依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webmvc</artifactId>
    </dependency>

    <!-- Spring AI OpenAI 启动器(兼容阿里云通义千问) -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>

    <!-- 测试依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webmvc-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<!-- Spring AI 版本统一管理 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

1.3 应用配置(application.properties)

核心配置:对接阿里云 DashScope 兼容 OpenAI 协议地址,填入 API-Key 并指定默认模型:

复制代码
spring.application.name=springai
server.port=8080

# 阿里云百炼 API Key
spring.ai.openai.api-key=
# 阿里云通义千问 OpenAI 兼容接口地址(核心)
spring.ai.openai.base-url=https://dashscope.aliyuncs.com/compatible-mode/v1
# 默认调用模型
spring.ai.openai.chat.model=qwen-max

说明:阿里云 DashScope 提供了完整的 OpenAI 协议兼容层,接口请求、响应格式与原生 OpenAI 完全一致,因此可直接使用 OpenAI 依赖调用通义系列模型。

二、两种同步调用实现方案

下面分别使用 ChatClient(高阶封装)和 ChatModel(底层原生接口)实现同步问答接口,两段代码均基于上述环境正常运行。

2.1 方案一:ChatClient 高阶封装写法

ChatClient 是 Spring AI 在上层封装的工具类,屏蔽了底层请求构建、结果解析细节,代码极简,是业务开发首选

复制代码
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ChatController {

    // 注入高阶客户端
    private final ChatClient chatClient;

    public ChatController(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    /**
     * ChatClient 同步问答接口
     * 特点:链式调用,自动构建请求、解析响应
     */
    @RequestMapping("/chat")
    public String chat(@RequestParam(value = "message") String message) {
        return this.chatClient.prompt()
                .user(message)  // 传入用户提问
                .call()         // 同步调用大模型
                .content();     // 直接获取对话内容
    }
}

2.2 方案二:ChatModel 底层原生写法

ChatModel 是 Spring AI 最核心的底层接口,所有模型调用最终都会基于它实现。需要手动构建请求对象、手动解析响应结果,灵活性更高。

复制代码
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ChatModelController {

    // 注入底层模型接口
    private final ChatModel chatModel;

    public ChatModelController(ChatModel chatModel) {
        this.chatModel = chatModel;
    }

    /**
     * ChatModel 同步问答接口
     * 特点:手动构建Prompt、手动配置模型参数、手动解析响应
     */
    @RequestMapping("/chat/model")
    public String chatModel(@RequestParam(value = "message") String message) {
        // 1. 手动构建请求,并指定模型为 qwen-max
        Prompt prompt = new Prompt(message, OpenAiChatOptions.builder()
                .model("qwen-max")
                .build());
        // 2. 同步调用模型,返回完整响应对象
        ChatResponse response = chatModel.call(prompt);
        // 3. 逐层解析响应,获取对话文本(当前版本使用 getText())
        return response.getResult().getOutput().getText();
    }
}

三、ChatClient 与 ChatModel 深度对比

结合代码实现,从设计定位、编码风格、灵活性、容错性等维度,全面对比两套接口的差异。

3.1 核心定位

  1. ChatModel Spring AI 体系的底层核心标准接口,是所有大模型调用的基础。框架不做额外封装,暴露原始请求、响应结构,偏向底层编程。
  2. ChatClient 基于 ChatModel 二次封装的高阶工具类,主打简化开发,屏蔽底层复杂对象与解析逻辑,面向业务场景设计。

3.2 多维度对比表

对比维度 ChatClient(高阶封装) ChatModel(底层原生)
代码复杂度 极低,链式调用,一行核心逻辑 偏高,需手动构建 Prompt、配置参数
请求构建 框架自动封装,无需手动创建请求对象 必须手动 new Prompt() 构造请求与参数
结果解析 自动解析,直接通过 content() 获取文本 逐层手动解析 ChatResponse 响应体
容错能力 内置空值、异常处理,安全性高 无自动容错,链式调用易触发空指针异常
扩展灵活性 较弱,仅支持通用配置,难以深度定制底层逻辑 极强,可精细化控制请求参数、响应处理逻辑
依赖关系 内部依赖 ChatModel 实现能力 框架基础接口,无上层依赖

3.3 适用场景建议

  • 优先使用 ChatClient:常规业务问答、快速开发、前后端对接等通用场景,提升开发效率。
  • 选择 ChatModel:底层调试、自定义模型参数、特殊请求改造、框架二次扩展等需要精细化控制的场景。

四、实战踩坑:getText()getContent() 取值问题解析

4.1 问题现象

在当前 2.0.0-M8 版本中,使用 ChatModel 解析响应时:

  • 调用 response.getResult().getOutput().getContent() → 无法获取有效内容;
  • 替换为 response.getResult().getOutput().getText() → 正常拿到大模型返回文本。

4.2 根因分析

该问题与大模型、协议、依赖无关 ,纯粹是 Spring AI 版本迭代导致的 API 命名变更

  1. 本文使用 2.0.0-M8,属于里程碑测试版 ,框架接口尚未稳定,输出文本的读取方法为 getText()
  2. 在 Spring AI 后续 正式版本(1.0 正式版 / 2.0 正式版) 中,框架统一规范命名,将方法修改为 getContent()

避坑建议:升级框架版本时,务必核对官方文档的 API 命名,避免因接口变更导致功能异常。

4.3 补充:阿里云 OpenAI 兼容模式原理

很多同学疑惑:为什么引入 OpenAI 依赖,却能调用通义千问?

  • 阿里云 DashScope 官方提供 OpenAI 协议兼容层 ,地址为 https://dashscope.aliyuncs.com/compatible-mode/v1
  • 该兼容层完全对齐 OpenAI 的请求报文、响应报文格式;
  • Spring AI OpenAI 启动器按照 OpenAI 协议解析数据,因此可以无缝对接通义千问、通义万象等阿里云模型,无需切换专属依赖。
java 复制代码
private static @Nullable String getContentFromChatResponse(@Nullable ChatResponse chatResponse) {
    return (String)Optional.ofNullable(chatResponse)
            .map(ChatResponse::getResult)       // 取结果
            .map(Generation::getOutput)         // 取输出消息
            .map(AbstractMessage::getText)      // 取文本(你的版本用getText)
            .orElse((Object) null);             // 空值返回null
}

我们来看一下ChatClient的底层.content的封装 就是ChatModel不就正是的return返回吗,

相关推荐
小飞侠在吗1 小时前
AI Agent Plan-and-Execute 技术范式详细文档总结
人工智能·agent·ai编程
东方佑1 小时前
碱基互补语言模型
人工智能·语言模型·自然语言处理
ん贤1 小时前
深度学习入门笔记(一)
人工智能·笔记·深度学习
Java面试题总结1 小时前
Python 文件基本操作
大数据·人工智能·python
weixin_509138341 小时前
科技报道:从“概率生成”到“认知领航”
人工智能·agi·智能体·智能体认知
MartinYeung51 小时前
[论文学习]差分隐私在机器学习中的演进:从符号式AI到大型语言模型
人工智能·学习
AdCj31 小时前
GitHub 日榜速递 (2026-06-08):AI 基础设施正在“下沉“
人工智能·github·agent
实在智能RPA1 小时前
RPA-Agent的自主规划边界在哪里?——2026:从指令执行到目标驱动的技术跨越
大数据·人工智能·ai·rpa
星川皆无恙1 小时前
基于BERT+LSTM+CRF与知识图谱的医疗智能问答系统实战:Neo4j图数据库+实体识别+意图分析完整项目
数据库·人工智能·深度学习·bert·lstm·知识图谱·neo4j