Spring AI 里 ChatClient 和 ChatModel 有什么区别?什么时候该用哪个?

结论先行:

  1. ChatClient 与 ChatModel 不是替代关系 :ChatClient 是高层业务调用 API,ChatModel 是底层模型调用抽象;ChatClient 通常封装 ChatModel。

  2. 共用方式优先选"统一 AiService + 底层共用 ChatModel" :业务代码只依赖 AiService,实现层用 ChatClient,避免业务到处直接绑定具体模型厂商。

  3. 多模型场景不要全局可变替换 ChatModel :应配置多个不可变 ChatModel/ChatClient,通过显式路由按业务选择,避免并发请求互相影响。

一. 核心区别

对比项 ChatClient ChatModel
定位 高层业务调用 API 底层模型调用接口
主要用途 组织业务对话流程 调用具体大模型
Prompt 构建 提供流畅式 API 通常接收标准化请求对象
Advisor 等扩展 可集成 不属于核心职责
普通调用 call()、content() 等 call(Prompt)
流式调用 stream() stream(Prompt)

具体方法会因 Spring AI 版本有所差异。

简单理解:

  • ChatClient 面向应用开发者,负责组织对话调用,包括 Prompt、Advisor、上下文和输出转换。

  • ChatModel 是统一模型调用接口,负责生成响应、流式生成和统一模型请求,底层由 OpenAI、Anthropic、Ollama 等具体实现适配。

注意:ChatClient 不是另一个大模型,它通常是对 ChatModel 的上层封装。

二. 为什么两者都存在?

直接调用 ChatModel:

java

复制代码
ChatResponse response = chatModel.call(
    new Prompt("请介绍一下 Spring AI")
);

使用 ChatClient:

java

复制代码
String answer = chatClient.prompt()
    .user("请介绍一下 Spring AI")
    .call()
    .content();

ChatClient 更适合组织业务逻辑;ChatModel 更适合统一模型调用、底层适配和基础设施封装。

三. 如何做到共用?

先明确:你想共用的是模型实例、业务代码,还是整个调用流程。通常有三种方案。

方案 A:多个业务模块共用同一个 ChatModel

适合多个服务模块都需要调用同一个模型的场景。

java

复制代码
@Configuration
public class AiConfig {

    @Bean
    public ChatClient chatClient(ChatModel chatModel) {
        return ChatClient.builder(chatModel).build();
    }
}

业务层注入 ChatClient;需要更底层控制的模块可以直接注入 ChatModel。这样可以共用底层模型配置和模型客户端,避免重复创建实例。

方案 B:封装统一 AI 服务(更推荐)

如果项目里有多个业务,例如客服、知识库、文本总结,不建议让业务代码到处直接依赖 ChatModel。可以统一封装:

java

复制代码
public interface AiService {

    String chat(String prompt);

    Flux<String> stream(String prompt);
}

实现层使用 ChatClient:

java

复制代码
@Service
public class DefaultAiService implements AiService {

    private final ChatClient chatClient;

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

    @Override
    public String chat(String prompt) {
        return chatClient.prompt()
            .user(prompt)
            .call()
            .content();
    }

    @Override
    public Flux<String> stream(String prompt) {
        return chatClient.prompt()
            .user(prompt)
            .stream()
            .content();
    }
}

这里的 Flux 需要 Reactor 依赖,且具体流式返回类型要与所用 Spring AI 版本匹配。

优点:

  • 业务代码只依赖 AiService,不绑定具体模型厂商;

  • 可以统一处理日志、超时、异常、限流和监控;

  • 更换模型或调整调用方式时,主要修改实现层;

  • 普通调用与流式调用可以共用统一业务入口。

方案 C:共用 ChatClient,但动态切换模型

如果不同业务需要不同模型,例如普通对话使用低成本模型、复杂推理使用高性能模型,可以配置多个 ChatModel 或 ChatClient,通过路由层按业务选择。

不要简单地把一个全局可变的 ChatModel 来回替换,否则并发请求可能互相影响。更稳妥的做法是使用不可变配置和显式路由。

相关推荐
§ꦿCFོ༉37 分钟前
嵌入式八股文—C语言入门学习(四)
c语言·开发语言·学习
Miya_Ye1 小时前
AI工具 Phoenix
ai·工具
投图匠1 小时前
十种不同风格的 CTP接口 框架
开发语言·python
吴名氏.2 小时前
Java转AI Agent教程(第十三周)混合检索与重排
java·数据库·人工智能·ai·ai agent
.痞老板.2 小时前
java ee--多线程(进阶)
java·java-ee
深入云栈4 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
爱笑的k114 小时前
nano-vllm 源码剖析:千行 Python 手写离线推理引擎的调度、显存与并行时序
开发语言·python·vllm
wang_shu_mo_ran5 小时前
MyBatis 从入门到进阶(一)
java·spring·mybatis
七夜zippoe5 小时前
Agent 无限循环烧 Token:死循环检测与中断机制设计
ai·agent·token·死循环·中断机制
X1A0RAN5 小时前
PPT 图片批量处理教程:导出全部幻灯片 · 提取全部素材
开发语言·javascript·powerpoint