Skip to content

Spring AI 的 ChatClient、Advisors、RAG 应该怎么理解

很多 Java 团队第一次接触 Spring AI 时,容易把它理解成:

  • 一个“帮 Spring 调大模型”的 SDK
  • 或者一个“直接做 Agent 平台”的框架

这两种理解都不够准确。

Spring AI 更适合被理解成:

  • 把常见 AI 能力纳入 Spring 统一抽象的一层基础框架

先说结论

如果你现在想在 Spring Boot 应用里做下面这些事情:

  • 调用聊天模型
  • 做结构化输出
  • 接入工具调用
  • 做会话记忆和 RAG
  • 把这些调用放进现有观测体系

Spring AI 是很自然的一层基础设施。

它最重要的价值,不是“花哨”,而是让这些能力以更像 Spring 的方式组织起来。

如果再往前走一步,更实用的结论通常是:

text
先用 Starter + ChatClient 把调用跑通,
再用 Advisors 接记忆、RAG 和日志,
最后再决定是否需要更上层的 Agent / Workflow 框架。

一、先别急着看 Agent,先把 Spring AI 的落地层级想清楚

Spring AI 真正适合回答的问题,不是:

  • “我能不能一上来就做一个复杂多智能体平台”

而更像:

  • “我怎么把模型调用、结构化输出、RAG、Tool Calling 先稳稳接进现有 Spring Boot 应用”

一条更常见的落地层级通常是:

  1. 先选模型 Starter,把调用跑通
  2. 再用 ChatClient 把业务入口组织好
  3. 再用 Advisors 接记忆、检索、日志和调试
  4. 最后才考虑复杂编排是不是应该交给更上层框架

如果你把这个顺序反过来,最容易出现的结果就是:

  • 项目复杂度长得比业务价值更快

二、先看 Starter:Spring AI 的第一步不是写 Prompt,而是把模型接进 Boot

Spring AI 的第一层价值,首先体现在 Starter 上。

对 Spring 团队来说,Starter 带来的不是“少写几行依赖”,而是:

  • 自动配置更统一
  • 模型 Bean 生命周期更清楚
  • 配置项进入 Spring Boot 体系

这决定了你后面做本地调试、环境切换、灰度验证时会不会很乱。

一个更实用的使用原则是:

  • 每次先只接一个主模型,把最小闭环跑通
  • 不要一开始就同时接聊天模型、Embedding 模型、图片模型、语音模型

因为真实项目里最容易先稳定下来的,通常是:

  • 一个聊天模型
  • 一个 Embedding 模型
  • 一个向量库

这三件事已经够你把第一版 RAG 服务跑起来了。

三、ChatClient:它是最常用的应用层入口

Spring AI 里最值得先建立直觉的一个点,就是 ChatClient

它的角色更像:

  • 面向业务代码的高层调用入口

而不是底层模型协议本身。

为什么这点重要?

因为真实项目里,大多数开发者关心的不是“模型 HTTP 请求长什么样”,而是:

  • 怎么把 system / user message 组织起来
  • 怎么接 Tool Calling
  • 怎么把 RAG、Memory 这些横切能力加进去
  • 怎么把结果转成结构化对象

ChatClient 的存在,就是为了把这件事做成更贴近 Spring 风格的调用体验。

一个更适合落地的组织方式通常是:

  • Controller 不直接拼 Prompt
  • Controller 调业务 Service
  • 业务 Service 内部持有 ChatClient
  • Prompt 模板、结构化输出、Advisors 都收敛在这一层

这样做的好处是:

  • HTTP 层不会和模型细节耦合
  • 后面要换模型或接记忆、RAG 时,不用把控制器全改一遍

一个更像真实业务代码的例子

下面这段代码不追求覆盖所有细节,但很接近真实项目里“先把聊天能力包成业务服务”的写法:

java
@Service
public class KnowledgeAnswerService {

    private final ChatClient chatClient;

    public KnowledgeAnswerService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    public AnswerResult answer(String question, String tenantId) {
        return chatClient.prompt()
                .system("""
                        你是企业知识库助手。
                        回答时优先使用检索结果,不确定时明确说不知道。
                        """)
                .user(question)
                .advisors(advisorSpec -> advisorSpec
                        .param("tenantId", tenantId))
                .call()
                .entity(AnswerResult.class);
    }
}

这里最重要的不是 API 写法本身,而是三件事:

  • ChatClient 由 Spring 管
  • 业务参数通过 advisor context 往下传
  • 返回值尽量直接收敛成结构化对象

四、Structured Output:别只停在“返回一段字符串”

很多团队接模型的第一版都会这样写:

  • 调模型
  • 拿到一段文本
  • 自己再用正则或字符串处理拆字段

这在 PoC 阶段可以接受,但很快就会变脆。

Spring AI 在结构化输出上的价值,是让你更早进入:

  • “模型返回的是一个业务对象”

而不是:

  • “模型返回一段自由文本,后处理再赌一把”

这种能力特别适合:

  • 摘要
  • 分类
  • 关键词抽取
  • 表单生成
  • 工单归类
  • 审核结果判定

一个常见的误区是:

  • 觉得结构化输出只是“把 JSON 解析成对象”

更重要的其实是:

  • 你把返回结果的稳定性要求提前显性化了

这会直接改善后面:

  • 接口契约
  • 单元测试
  • 失败重试
  • 风险兜底

五、Advisors:它更像 AI 请求链上的增强器

很多人第一次看到 Advisors,会把它误会成某种“插件系统”。

更准确的理解方式是:

  • 它像 AI 请求链路上的拦截和增强层

这一层特别适合承载重复模式,比如:

  • 会话记忆
  • RAG 检索增强
  • 日志和调试
  • 某些统一参数注入

这也是 Spring AI 很有工程味的一点:

  • 不把所有逻辑都塞进一次 prompt 组装里
  • 而是把横切模式拆成可组合、可复用的增强层

如果你已经熟悉 Spring 里 Filter、Interceptor、Advice 这一类思路,会很容易理解它的价值。

更实用的 Advisor 心法

真实项目里可以优先把 Advisors 分成三类:

1. 上下文类

比如:

  • Chat Memory
  • RAG
  • 某类用户态信息注入

2. 调试类

比如:

  • 请求日志
  • 响应日志
  • Prompt 调试

3. 控制类

比如:

  • 统一限流标签
  • 安全开关
  • 某些租户级参数透传

这么拆的好处是:

  • 你以后排问题时,知道是哪一层在改模型输入

一个更贴近实战的 Advisor 组合例子

java
var response = chatClient.prompt()
        .user(question)
        .advisors(
                messageChatMemoryAdvisor,
                questionAnswerAdvisor,
                simpleLoggerAdvisor
        )
        .call()
        .content();

这种顺序通常要自己想清楚:

  • 先补历史
  • 再补检索
  • 最后看日志

如果顺序乱了,你经常会出现:

  • 以为是 RAG 没召回
  • 实际是 Memory 先把上下文污染了

六、Chat Memory:别一上来就把所有历史都塞回模型

很多团队第一次接记忆,默认动作都是:

  • 把过去所有对话都拼回去

这通常很快就会出问题:

  • Token 飙升
  • 延迟上升
  • 历史噪音越来越多
  • 关键问题被老上下文稀释

更稳的使用方式通常是:

  • 短对话先用窗口式记忆
  • 长对话再考虑摘要式记忆
  • 严格区分“会话记忆”和“业务事实”

这句话很重要:

  • 会话记忆适合保留这轮上下文
  • 业务事实更适合进数据库、缓存或检索系统

不要让 Chat Memory 承担本来应该由业务存储承担的职责。

七、Spring AI 里的 RAG,不只是“查向量库”

很多团队说自己在做 RAG,实际做的只是:

  • 把用户问题拿去查一下向量库
  • 再把结果拼到 prompt 里

这当然能跑,但工程上往往不够稳。

Spring AI 在 RAG 上的价值,是把它往“可组合能力”方向推了一步。

你可以理解成:

  • 模型调用是一层
  • 检索增强是一层
  • 对话记忆又是一层

这样做的好处是:

  • RAG 不再只是一个散落在业务代码里的小技巧
  • 而是能成为统一调用链的一部分

这对后面做:

  • 文档问答
  • 企业知识库检索
  • 对话式运维助手
  • 带上下文的业务 Copilot

都更容易长期维护。

实战里更常见的两种起步方式

1. 先从 QuestionAnswerAdvisor 起步

适合:

  • 先把“检索一下再回答”跑通
  • 业务复杂度还不高

它更像:

  • 一个较轻的 RAG 入口

2. 复杂度上来后转向 RetrievalAugmentationAdvisor

适合:

  • 需要更细控制检索链路
  • 需要 Query Transform、Document Join、Contextualizer 这一类组件能力

这时你通常已经不再满足:

  • “只要查出来几段文本塞进去就行”

而是开始关心:

  • 查询改写
  • 多路召回
  • 文档压缩
  • 注入方式
  • 输出是否真的引用到召回内容

一个更贴近业务演进的判断

更稳的路线通常是:

  1. 第一版先用轻量 RAG 跑通场景
  2. 第二版开始补 metadata filter、chunk 策略和召回质量
  3. 第三版再进入更细粒度的 Retrieval Augmentation 组件编排

八、Tool Calling 是“让模型接动作”,不是让模型替你写业务

Spring AI 也提供 Tool Calling 能力。

但这里最容易出现一个误区:

  • 以为只要把工具注册进去,模型就自动变成完整 Agent

实际上更稳的理解是:

  • Tool Calling 负责把“调用外部动作”的能力标准化
  • 但业务流程控制仍然需要你自己决定

这意味着 Spring AI 很适合做:

  • 查天气
  • 查库存
  • 调内部接口
  • 触发某类受控动作

但如果你已经进入:

  • 多步骤规划
  • 多角色协作
  • 长生命周期状态控制

那你通常就会开始需要更上层的 Agent / Workflow 编排能力。

实战里最重要的一个边界

工具调用适合暴露:

  • 幂等查询
  • 有明确权限边界的动作
  • 输入输出清晰的业务能力

不适合一上来就暴露:

  • 大范围写操作
  • 高风险删除操作
  • 缺少审计的资金或权限动作

更保守的路线通常是:

  • 先让模型只能“查”
  • 再让模型在审批或二次确认后“改”

九、一个更像真实项目的最小分层

如果你准备在 Spring Boot 里长期用 Spring AI,一个更稳的最小分层通常是:

1. Controller 层

  • 只处理 HTTP 输入输出
  • 不直接拼 Prompt

2. AI Application Service 层

  • 负责 ChatClient
  • 负责挂 Advisors
  • 负责结构化输出
  • 负责决定是不是接工具、记忆、RAG

3. Retrieval / Tool Adapter 层

  • 封装向量库
  • 封装业务工具
  • 封装外部 API

4. Domain / Repository 层

  • 放真正业务事实和持久化逻辑

这样分层的最大好处是:

  • 以后你换模型、换 Embedding、换向量库、换 Prompt,不会一路改到 Controller 和 Domain

十、可观测性是 Spring AI 很容易被低估的一点

很多团队前面都把注意力放在:

  • 支不支持模型
  • 能不能接向量库
  • 有没有 Tool Calling

但真正进入生产后,你会越来越在意:

  • 这次调用到底慢在哪
  • 哪个 Advisor 在放大延迟
  • 哪次检索命中了什么文档
  • Token 用量和异常分布是什么样

Spring AI 把可观测性纳入核心组件视角里,这对 Spring 团队是很重要的加分项。

因为它意味着:

  • AI 调用不会天然成为一块不可见黑盒

更实用的落地建议

至少建议把下面几类信息纳入观测:

  • 模型名
  • Token 用量
  • 调用耗时
  • Advisor 链路
  • 检索条数
  • 失败类型

如果你后面要做成本治理、慢查询排查和回答质量回溯,这些信息都会用上。

十一、什么时候只用 Spring AI 就够了

下面这些场景,通常只用 Spring AI 就已经足够:

  • 文档问答
  • 智能摘要
  • 文本分类和抽取
  • 简单业务助手
  • 带知识库的客服或内部问答
  • 受控工具调用的业务 Copilot

这些问题的共同特点是:

  • 核心难点还在“模型接入 + 检索增强 + 工具调用”
  • 而不在“复杂编排系统”

十二、什么时候该往更上层框架看

如果你开始遇到下面这些问题:

  • 需要多 Agent 协作
  • 需要顺序、并行、循环、路由控制
  • 需要更强的长流程状态管理
  • 需要人机协同审批
  • 需要可视化 Prompt / Agent 运维与评估

那你通常就会开始看:

  • Spring AI Alibaba
  • 或其他更偏 Agent / Workflow 的上层框架

十三、最常见的几个落坑点

1. Prompt、RAG、Memory 全堆在一个方法里

这会让调用链越来越不可维护。

2. 把 Chat Memory 当业务数据库

这会让上下文越来越脏,也让问题越来越难复现。

3. 一上来就追求复杂 Agent,而不是先把单 Agent 服务做稳

这会让复杂度和风险远早于价值出现。

4. 没有做结构化输出和观测,就直接进入生产

这样后面很难排查“模型到底是答错了,还是流程没接好”。

一句话总结

Spring AI 最适合被当成 Spring Boot 应用里的 AI 基础设施层来理解。

更稳的落地顺序通常是:

  • Starter 先接通模型
  • ChatClient 收敛业务入口
  • Advisors 接记忆、RAG 和日志
  • Tool Calling 只暴露受控动作
  • 观测先于复杂编排

先把这条主线做稳,再决定是否继续往 Agent 编排层上走,通常更适合真实项目。

参考资料

把零散经验整理成可查、可复用、可持续更新的企业级知识门户