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 分钟前
Cognee:面向 AI 智能体的开源记忆平台
人工智能·python
东风破_4 分钟前
把一篇网页放进 RAG 知识库:Loader、文档切分与语义检索实战
人工智能
禅与计算机程序设计艺术6 分钟前
【DeepThink Research】长程任务 Agent 的工程实现机制:中断续跑、记忆分层、长上下文不丢失与分布式优雅升级
人工智能
糖果店的幽灵7 分钟前
【langgraph 从入门到精通graphApi 篇】Command 与动态流程控制
android·java·数据库·人工智能·langgraph
深蓝AI9 分钟前
KTransformers 实战:消费级显卡本地跑满血 DeepSeek,CPU-GPU 异构推理全攻略
人工智能
魏祖潇9 分钟前
AI幻觉不是用更大模型解决——RAG增强+引用溯源+置信度标注让AI开口必带出处
人工智能·ai编程
QN1幻化引擎10 分钟前
认知架构调度与语言模型辅助:DalinX V8 Track 1 实验报告
人工智能·语言模型·架构
大模型丫丫11 分钟前
Agent开发的难点是什么呢?
大数据·人工智能·学习
kp0000015 分钟前
NER(Named Entity Recognition)命名实体识别
人工智能·网络安全·信息安全·ai安全
hqyjzsb15 分钟前
非计算机专业学生怎么进入AI相关方向
人工智能·职场和发展·金融·数据挖掘·数据分析·aigc·业界资讯