欢迎光临
我们一直在努力

[AI工程] Spring AI第一篇:2.0 到底升级了什么?从 Prompt、RAG、MCP 到 Agent 应用实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}

💡 这两年 Java 开发者做 AI 应用,已经不只是"调一个大模型接口"这么简单了。企业数据怎么接进来、工具怎么让模型安全地调、RAG 怎么拆成能替换的模块、Agent 工作流怎么控制在能审计的范围内——这四件事哪一件都没法靠一个 chat() 方法解决。

如果项目本身就是 Spring Boot,那 Spring AI 值得重点关注。它的定位很克制:不训练模型,也不做算法那套,只负责把企业数据、业务 API 和 AI 模型连起来,并且连的方式要符合 Spring 工程习惯——自动配置、可注入、可测试、可观测。

2.0 的变化又比一般版本号大得多。官方 Getting Started 直接写明"Spring AI 2.0.x supports Spring Boot 4.0.x and 4.1.x",同时把 Model、Advisor、Tool Calling、MCP、RAG 五块各自重构了一遍。也就是说,从 1.x 抄来的示例不是"能跑但不好看",而是有几处会静默失效:工具注册的字符串 bean 名不再被识别,ChatClient.builder(chatModel) 手工造出来的客户端不带观测,工具循环也从模型实现内部挪到了一个 Advisor 上。

所以这篇从工程落地角度把 2.0 梳一遍:它到底解决什么问题、五块地基各自怎么变的、每块能配到什么程度,以及 Java 开发者在项目里该怎么选——包括和 LangChain4j 的分工。文中所有 API 形状与版本结论,按官方 2.0.1 参考文档与本地 sources jar 逐条核对过。

Spring AI 2.0 工程落地全景


1. 2.0 到底动了哪些地基

先把定位钉住:Spring AI 是连接层,不是模型层。

企业数据 / 业务 API / MCP 工具
↓
Spring AI 编排层(ChatClient + Advisor 链)
↓
OpenAI / Qwen / DeepSeek / Claude / 本地模型(Ollama)

简单理解:模型负责"思考",Spring AI 负责"把它接进你的工程体系"——配置、拦截、检索、工具、观测、重试这六件脏活。

1.1 版本基线

项2.0.1 的实际情况
Spring AI 官方稳定版 2.0.1(文档正文按 2.0.x 表述)
Spring Boot 4.0.x / 4.1.x(官方 Getting Started 原句)
JDK Getting Started 页未单独声明;Boot 4 自身要求 Java 17 起,涉及虚拟线程与并行的写法我会按 21+ 标注(这条是个人建议,不是官方契约)
模型通道 OpenAI / Anthropic / Gemini / DeepSeek / Ollama / ZhiPuAI 等 starter,统一走 Model API
Maven 坐标 spring-ai-bom + 各 spring-ai-starter-*

有一条对国内项目影响很大:Spring AI Alibaba 的 DashScope starter 目前对应的还是 Spring AI 1.1.2(1.1.2.0 依赖 Boot 3.5.8)。所以"2.0 的新类名"在你的项目里未必存在,本篇凡是 2.0 才成立的写法,我都会标一句 1.x 的对应形式。

1.2 1.x → 2.0 对照

维度1.x2.0
Spring Boot 3.x 4.0.x / 4.1.x
模型抽象 各模型 API 为主 统一的 Model API
Advisor 基础增强链 CallAdvisor / StreamAdvisor 两类接口 + BaseAdvisor 默认实现
Tool Calling 模型实现内部的 while 循环 ToolCallingAdvisor 统一编排,可插进 Advisor 链
MCP 基础集成 注解驱动(@McpTool / @McpResource / @McpPrompt / @McpComplete)+ 四种传输 + 客户端/服务端 starter
RAG 传统问答增强 Naive RAG(QuestionAnswerAdvisor)+ Modular RAG(RetrievalAugmentationAdvisor)
可观测性 基础指标 深度接入 Micrometer Observation,Advisor / ChatClient / Model / Tool / VectorStore 五个观测点

我的理解是:

Spring AI 2.0 的重点不是"多支持几个模型",而是让 AI 能力真正进入 Spring 工程体系:可组合、可测试、可观测、可维护。

Spring AI 2.0 核心能力分层

Q1:2.0 的变化要不要重写一遍存量代码?

不用重写,但有四处必须动手,且都属于"不改也不报错"那一类:

位置1.x 写法2.0 改法
工具注册 defaultTools("beanName") / defaultToolCallbacks(…) defaultTools(Object…)(defaultToolCallbacks 已 forRemoval)
工具循环 手工依赖模型内部循环 用 ToolCallingAdvisor;自己再注册一份会撞——链上最多一个 ToolAdvisor,多一个直接 IllegalStateException
客户端构造 ChatClient.builder(chatModel) 注入 ChatClient.Builder Bean;静态工厂的 ObservationRegistry 是 NOOP,等于自断可观测
类名 ToolCallAdvisor ToolCallingAdvisor(前者已废弃并继承自后者)

2. PromptTemplate:把提示词当代码管,而不是当字符串管

提示词的工程化,其实只有三个动作:模板化、变量校验、版本化。

业务方常把提示词理解成"一段字符串"。真实项目里它至少要满足:能外置到资源文件、变量能类型化注入、改动能被 review、上线前能跑测试。PromptTemplate 默认用 {} 作为变量分隔符(源码里就是 DEFAULT_START_DELIMITER_TOKEN = '{' / '}'),并且支持自定义渲染器:

PromptTemplate promptTemplate = PromptTemplate.builder()
.renderer(StTemplateRenderer.builder()
.startDelimiterToken('<')
.endDelimiterToken('>')
.build())
.template("推荐 5 部 <director> 的代表电影。")
.build();

String prompt = promptTemplate.render(Map.of("director", "周星驰"));

一个容易撞上的细节:StTemplateRenderer 的 validationMode 默认是 THROW——模板里有变量、渲染时没传,直接抛异常,而不是留个空串静默发出去。这个默认值对生产是好事(少一类"提示词莫名其妙缺一段"的排查),但如果你把模板写成"有变量就填、没有就算了"的宽松风格,要么补齐变量,要么显式换成 WARN。

什么时候必须换分隔符?答案很具体:提示词里要放 JSON。{ } 和模板变量撞了,ST4 会把 JSON 的键当变量解析。三种处理方式按侵入性排:

方式做法代价
换分隔符 startDelimiterToken('<') 最直接,模板要和别人共享时不友好
转义 用 ST 的字面量转义写法 可读性差,容易被格式化插件吃掉
结构化输出替代 不让模型读 JSON 片段,改用 output schema 约束 要走 BeanOutputConverter / StructuredOutputConverter 那套(2.0 里由 StructuredOutputValidationAdvisor 兜校验重试),详见第七篇

一句话理解:PromptTemplate 解决"怎么组织输入",Advisor 解决"怎么在一次调用前后统一增强"。 前者是内容层,后者是链路层。


3. Advisor:一次模型调用的横切面,order 决定谁在外层

2.0 把"拦截器"这件事正式接口化了,也把顺序问题正式抛给了你。

用户请求
–> Memory Advisor(+200,最外层)
–> Tool Calling Advisor(+300,循环 N 轮)
–> RAG / Logger Advisor(0,每轮都跑)
–> Chat Model
–> 响应增强 / 监控 / 审计(反序回溯)

Spring AI 2.0 把 Advisor 分成两类接口,方法签名(源码核对):

类型场景核心方法
CallAdvisor 普通同步调用 adviseCall(ChatClientRequest, CallAdvisorChain)
StreamAdvisor 流式响应 adviseStream(ChatClientRequest, StreamAdvisorChain)
BaseAdvisor 只想写前/后逻辑 提供上面两个方法的默认实现,你只填 before* / after*

执行规则:按 getOrder() 升序进入(数值越小越靠外层),响应阶段反序返回。order 相同则相对顺序不保证——链上只要有两个默认值为 0 的 Advisor(比如 RAG 和 Logger),谁先执行就是随机的,要固定就得显式给值。

Q2:Advisor 适合放什么能力?

常见的横切逻辑都适合:对话记忆、RAG 上下文注入、内容安全、工具调用、请求审计、Token 与耗时统计、重试 / 降级 / 模型路由、结构化输出校验。

反过来,不适合放的是业务分支决策("这单要不要退"这类判定),那属于服务层职责——放进 Advisor 会让一次模型调用隐式承担业务写操作,出了事很难回放。

需要注意:自定义 Advisor 修改了请求后,必须把修改后的 request传给下一个节点。只 new 了一个拼装好的字符串却继续往下传原始 request,改动是不生效的——这是自写 Advisor 最常见的一个静默失败。

Q3:工具调用为什么从模型内部挪到了 Advisor?

因为循环位置决定了"谁会被重复执行"。1.x 时代工具循环埋在某个 ChatModel 实现里,换模型就换了行为;2.0 的 ToolCallingAdvisor(DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 300,同时实现 CallAdvisor / StreamAdvisor / ToolAdvisor)把它变成链上的一环,好处是可组合、可关掉内部历史(conversationHistoryEnabled(false) / disableInternalConversationHistory()),代价是你要开始关心排布。

2.0 会自动注册一个 ToolCallingAdvisor,所以"模型请求调用工具 → 应用执行 → 结果回传"这个循环通常不用你管。但有一点必须记住:模型只能提出调用请求,真正的执行权限在应用侧。这决定了鉴权、审计、超时、幂等这些控制放哪儿——只有这一层拦得住。


4. Memory、Tools、MCP:连接真实业务的三种粒度

三种粒度分别解决"记不住"、“办不了事”、“没法复用”。

4.1 对话记忆:窗口记忆和向量记忆不是一回事

ChatMemory 是抽象,默认实现是 MessageWindowChatMemory——只保留最近若干条消息,避免上下文无限增长:

MessageWindowChatMemory memory = MessageWindowChatMemory.builder().maxMessages(20).build();

持久化官方给了六种 ChatMemoryRepository:

实现存储备注
InMemoryChatMemoryRepository ConcurrentHashMap 默认,进程内
JdbcChatMemoryRepository 关系库 支持 PostgreSQL / MySQL / SQL Server / HSQLDB / Oracle
MongoChatMemoryRepository 文档库
CassandraChatMemoryRepository 宽表
Neo4jChatMemoryRepository 图
RedisChatMemoryRepository 缓存 / KV 需要 Redis Stack 7.0+

官方文档里没有 JpaChatMemoryRepository。想用 JPA 那套基础设施,落地方式是给它一个 JPA 背后的 DataSource 走 JDBC 实现,别照着"应该有个 JPA 版"去找类。

历史很长、又只需要召回相关片段时,换 VectorStoreChatMemoryAdvisor——它把历史写进向量库,按当前问题检索回来。两句话记住分工:短期记忆解决"刚才聊了什么";向量记忆解决"历史上哪些信息和当前问题有关"。

4.2 Tools:模型提议,应用执行

@Component
class DateTimeTools {

@Tool(description = "获取用户时区下的当前日期和时间")
String getCurrentDateTime() {
return LocalDateTime.now()
.atZone(LocaleContextHolder.getTimeZone().toZoneId())
.toString();
}
}

description 是模型唯一的选工具依据,所以它属于接口设计而不是注释——写完工具真正要花在排查上的时间,多半是"它为什么没调这个工具 / 为什么调错了"。参数校验、权限、超时、幂等这些放哪儿,第八篇按七个痛点逐个给过做法。

4.3 Tool Calling 与 MCP:一个是应用内调用,一个是跨应用协议

能力Tool CallingMCP
本质 模型请求应用调用某个函数 工具、资源、Prompt 的标准化协议
范围 当前应用内部 跨应用、跨进程、跨团队共享
典型用法 查订单、发消息、调业务服务 连 GitHub、数据库、内部工具平台
Spring AI 入口 @Tool @McpTool、@McpResource、@McpPrompt、@McpComplete(参数用 @McpToolParam)

一句话结论:@Tool 解决"模型能不能用我的方法",MCP 解决"我的能力能不能被别人复用"。

MCP 在 2.0 里支持四种传输,且各对应不同 starter:

传输对应 starter
STDIO spring-ai-starter-mcp-server
SSE spring-ai-starter-mcp-server
Streamable HTTP spring-ai-starter-mcp-server-webflux
Stateless Streamable HTTP spring-ai-starter-mcp-server-webmvc
客户端 spring-ai-starter-mcp-client / spring-ai-starter-mcp-client-webflux

客户端侧另有一组注解处理服务端反向通知:@McpLogging、@McpSampling、@McpElicitation、@McpProgress、@McpToolListChanged 等。

这里给一句和第 1 章同源的提醒:MCP Server 不是天然可信的组件。它把工具、资源、Prompt 都变成了远程可返回内容的入口,而这些内容最终会进你的 prompt——鉴权、域名白名单、返回值信任边界这三件事必须自己定,第九篇有完整的落地写法。


5. RAG:别停在"文档切块 + 向量检索"

RAG 的难点不在 Advisor 怎么配,而在你放进去的片段质量和能不能稳定把它捞出来。

文件 / Wiki / 数据库
–> 文档解析与切分(Reader / Transformer)
–> Embedding 向量化
–> Vector Store
–> 检索相关内容(Retriever + 过滤表达式)
–> 注入 Prompt(QueryAugmenter)
–> LLM 生成答案

2.0 把 RAG 分成两类,选型的分水岭是"要不要控制检索过程":

模式组件适合场景
Naive RAG QuestionAnswerAdvisor FAQ、简单知识库问答、单库单语言
Modular RAG RetrievalAugmentationAdvisor 复杂检索、多知识库、需要权限过滤的生产问答

Modular RAG 的价值在于每个环节都是可替换组件:

用户问题
–> QueryTransformer:改写 / 翻译 / 多查询扩展
–> DocumentRetriever:多路检索(可带 filterExpression)
–> DocumentJoiner:合并去重
–> QueryAugmenter:注入上下文
–> LLM

Q:什么时候真的值得从 Naive 升到 Modular?

我按四个信号判断,中一个就升:

信号为什么 Naive 不够
用户问法模糊、需要改写或多查询扩展 Naive 只拿原问题搜一遍
文档多语言 / 多来源 没有 QueryTransformer 与 Joiner 的位置
要按用户或租户隔离资料 需要显式的 filterExpression 链路,且请求期注入
要评估检索质量 需要拿得到检索到的文档(DOCUMENT_CONTEXT),Naive 给的是 qa_retrieved_documents

另外补一个工程顺序上的坑:RetrievalAugmentationAdvisor 默认 order 是 0,也就是在工具循环内侧——一次带工具的提问可能触发 2~3 次向量检索。想让它一次请求只检索一次,把 order 提到 HIGHEST_PRECEDENCE + 250(Memory 之后、工具循环之前)。这套排法第十一篇有完整推演。


6. Agent 与模型选型:先定边界,再谈自治

Spring AI 官方没有把 “Agent” 做成一个抽象类,它给的是可拼的积木。

6.1 五种典型工作流模式

模式一句话机制适合场景
Chaining 前步输出接后步输入 串行多步骤任务
Parallelization 分段并行 / 同任务多视角投票 并行调用后聚合
Routing 先分类再走专业分支 按问题类型路由到专门处理器
Orchestrator-Workers LLM 动态拆解 + 分派 + 合成 任务规模不可预知的复杂工作
Evaluator-Optimizer 生成 → 评估 → 带反馈重写,循环到达标 质量需要自我迭代(结构化输出校验就是它的特例)

真正的问题不是"要不要 Agent",而是这个任务的哪种不确定性值得交给模型。对大部分企业项目,我更建议从受控工作流开始,而不是一上来做全自治 Agent:

固定业务流程 –> 在关键节点调用 LLM –> 调用受控 Tools –> 结构化输出 –> 人工审核或规则校验

6.2 模型选型:先写约束,再列候选

不要先问"哪个模型最强",先明确任务:

你的约束优先考虑
追求最快上线、能力完整 云端商业模型 API
数据不能离开内网 私有化部署的开放权重模型
Token 成本敏感 小参数模型、路由策略、缓存与批处理
有垂直领域要求 自建评测集后,对候选模型实测
要训练专属模型 这是算法、数据与 MLOps 的能力范围,不是应用框架能替你解决的

模型参数量不是选型结论。真正要看的是你的业务数据、任务类型、延迟、成本、合规要求和评测结果。

另外提醒一个用词边界:严格来说很多"开源大模型"更准确叫 Open Weight(开放权重)——权重开放、训练代码开放、训练数据开放、可自由商用,这四件事不是一回事。企业内落地或对外分发前,单独查一次 License。

6.3 那 LangChain4j 和 Spring AI 怎么选?

两者都能做 Java AI 应用,也都支持模型接入、RAG、Tool Calling 与 MCP,不存在"无脑选哪个"。

维度LangChain4jSpring AI
框架依赖 可独立使用,也可集成 Spring 深度融入 Spring Boot
编程风格 AI Services 抽象较鲜明 更贴近 Spring 生态习惯
MCP 支持客户端,服务端能力有社区模块(MCP 文档) 客户端、服务端与注解模型更一体化
适合人群 非 Spring 项目、希望保持框架中立 Spring Boot 企业应用
版本基线 以官方文档为准 2.0.x 对应 Boot 4.0.x / 4.1.x

结论很简单:主项目已经是 Spring Boot,Spring AI 的自动配置、可观测性、MCP starter 与企业基础设施整合更省心;不依赖 Spring 或要保持框架中立,LangChain4j 完全值得考虑。 这一行的对比是写这篇时的快照——两边迭代都很快,真要选型,拿你手上的三个真实场景各跑一遍 POC 比看表格可靠。


7. 落地顺序与全景图

四步上手法,按"每步都能验收"来切。

7.1 笔者(后端 & 架构)的落地顺序

步骤做什么验收标准
① 先通链路 注入 ChatClient.Builder,接一个模型通道 + PromptTemplate + 结构化输出 同一问题问三次,返回的 JSON 能被同一个 DTO 反序列化
② 再给记忆 MessageWindowChatMemory + 一个持久化 repository,conversationId 服务端造 重启进程后历史还在,且换用户读不到别人的会话
③ 然后接能力 @Tool 起步(鉴权/审计/超时/幂等放应用侧),有跨团队复用需求才上 MCP 单请求的模型调用数在预期内;工具失败有可观测记录
④ 最后才谈检索与编排 Naive RAG 起步,命中第 5 章四个信号再升 Modular;Agent 模式按第 6 章决策 有评测集与通过率;有 trace 与 token 归因看板

四步里我最看重第 ④ 步的顺序:先把评测和可观测装上,再优化 RAG 和编排。没有这两样,改 topK、加 rerank、换 embedding 全是玄学,你只能凭感觉说"看起来准了"。

7.2 知识脉络图

Spring AI 2.0(2.0.1 / Boot 4.0.x-4.1.x)
├── 连接层定位:不训练模型,只连数据 / API / 模型;五块地基统一 Model API
├── Prompt:PromptTemplate 默认 {} 分隔符,ValidationMode 默认 THROW;JSON 场景换分隔符或走 schema
├── Advisor:Call/Stream 两接口 + BaseAdvisor 默认实现;order 小=外层,同值不定序
│ 坑:改了 request 必须往下传;链上最多一个 ToolAdvisor
├── Memory:MessageWindowChatMemory(窗口)+ 6 种 Repository;长期相关靠 VectorStoreChatMemoryAdvisor
├── Tools:@Tool(description=接口设计)+ ToolCallingAdvisor 统一编排;执行权限恒在应用侧
├── MCP:注解驱动 + STDIO/SSE/Streamable/Stateless 四传输;Server 不天然可信,边界自己定
├── RAG:Naive(QuestionAnswerAdvisor)→ Modular(RetrievalAugmentationAdvisor 全组件可换)
│ 默认 order=0 在工具循环内侧,要一次请求只检索一次就提到 +250
├── Agent:Chaining / Parallelization / Routing / Orchestrator-Workers / Evaluator-Optimizer
│ 先受控工作流,再谈自治
└── 选型:约束(合规/成本/延迟/评测)先于模型;Boot 项目 → Spring AI,中立 → LangChain4j

7.3 想继续往下读

这一篇是全景,每块能力各有一篇深入:接入与配置看第二篇,多模型 / 流式 / 工具第一轮跑通看第三篇,提示词技巧看第四篇,Advisor 自定义看第五篇,记忆的两种持久化实现在第六篇,结构化输出与 Tools 原理在第七、八篇,MCP 源码与鉴权在第九篇,RAG 全链路在第十篇,端到端客服实战在第十一篇,评测与幻觉防线在第十二篇,可观测与成本归因在第十三篇,五种模式的代码在第十四篇,Agent 工具箱在第十五篇。


最后总结

  • 如果你只是想快速接入一个模型:从 ChatClient、PromptTemplate 和结构化输出开始,别一上来铺架构。
  • 如果你需要让模型理解企业知识:先 Vector Store + QuestionAnswerAdvisor,命中第 5 章那四个信号之后再演进到 Modular RAG。
  • 如果你需要让模型调用业务能力:用 @Tool,并把鉴权、审计、超时、幂等全放在应用侧——模型只能"请求",能执行的是你。
  • 如果你准备做跨系统工具生态:上 MCP,但别把 MCP Server 当成天然可信的组件。
  • 如果你已经在线上了:先把可观测和评测装上(第十三、十二篇),再谈优化,否则所有调优都是猜。
  • 对后端 / 架构同学,我更想强调一句:Spring AI 2.0 的复杂度不在 API 数量,而在"谁在外层、跑几轮、出错算谁的"。这三件事它没有替你决定,也决定了它只是框架而不是方案。

Spring AI 2.0 最值得关注的地方,不是它让 Java 也能"调用大模型",而是它开始把 AI 应用纳入 Spring 擅长的工程体系:配置、测试、观测、安全和模块化。

一句话结论:把 Spring AI 当"连接层 + 拦截链"用,你会越用越顺;把它当"Agent 框架"指望它替你决策,你会在最贵的 token 上付学费。

参考资料 & 致谢

[1] Spring AI 官方项目页

[2] Spring AI 2.0.1 参考文档

[3] Spring AI Getting Started(版本兼容矩阵)

[4] Spring AI Advisors API

[5] Spring AI Tool Calling

[6] Spring AI Chat Memory

[7] Spring AI Prompt

[8] Spring AI MCP Annotations Overview

[9] LangChain4j 官方文档

[10] LangChain4j MCP 文档

[11] Spring AI Alibaba(DashScope 通道)

[12] AI工程 Spring AI 2.0 梳理 – 语雀

赞(0)
未经允许不得转载:171主机测评 » [AI工程] Spring AI第一篇:2.0 到底升级了什么?从 Prompt、RAG、MCP 到 Agent 应用实战
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址