大家好,今天想和大家分享的是关于 Spring AI 的链式工作流(Chain Wokrflow Pattern)的内容,并通过一个实际应用案例-博客文章生成器,教你如何轻松实现可靠的 AI 功能集成。

引言
基于Spring AI 及其Agentic 设计模式,我们现在可以很容易地借助大模型的能力构建智能体应用。在这篇文章中,我将首先介绍 Spring AI 五种核心Agentic 设计模式的相关概念,并以"链式工作流"模式为例,从零到一构建一个真实的应用。
在深入探讨各种模式之前,先理解一下基于代理的系统中两个关键的概念定义:
- 工作流 (Workflows) 就像是"跟团游"。所有流程都严格遵循开发者在代码中预设好的清晰路径。当你的需求是每次都得到同样的结果时,它就是绝佳选择------结果可预测且高度可靠。
- 代理 (Agents) 则更像是"自由行"。它们会根据当前任务,自主决定使用哪些工具、采取哪些步骤。这赋予了它们极大的灵活性,但其行为也因此更难预测。
在大多数商业和企业应用场景中,工作流往往是更优的选择,因为它们更易于控制、调试和维护。这也正是 Spring AI 重点支持基于工作流的模式的原因。
Agentic设计模式概览
Spring AI 提供了一套强大的 工作流模式,帮助你更好地组织大语言模型在应用中的行为,让你的 系统变得更易于管理、更加可靠。
下面是 Spring AI 支持的5种主要的工作流模式:
- 链式工作流 (Chain Workflow) :通过把一个大任务拆分成一系列易于管理的小步骤,环环相扣,下一步的执行建立在上一步的结果之上。 (这也是本文介绍的重点内容)
- 并行工作流 (Parallelization Workflow) :同时处理一个任务的多个部分,最后再将所有结果汇总。当多个子任务互不依赖时,这种模式能极大地提升速度和效率。
- 路由工作流 (Routing Workflow) :根据问题的类型或上下文,智能地选择最合适的处理逻辑或响应路径。举个常见的例子:一个智能客服,能自动将问题转给相应的业务部门。
- 编排器-工作者模式 (Orchestrator-Workers) :在这种模式下,编排器负责将一个复杂任务分解,并将这些小任务分配给不同的"工作者(Agent)"去执行。就像一位项目经理在协调整个团队高效协作。
- 评估器-优化器模式 (Evaluator-Optimizer) :该模式模仿了人类修改和完善工作的过程。一个 AI 负责生成初稿,另一个 AI 则负责审阅、提出反馈并要求改进。这个"生成-反馈-优化"的循环会一直持续,直到产出令人满意的结果。
Spring AI 借助其 聊天模型 (chat model) 和 工具执行 (tool execution) 功能,使得实现这些工作流变得异常简单,可以帮助我们处理绝大部分复杂的底层工作。
Spring AI 链式工作流模式
链式工作流模式的核心思想是:通过将复杂问题拆分为一系列连续的、可管理的步骤来简化问题。 想象一下,面对一个复杂难题,你不再是向大语言模型 (LLM) 下达一个庞大而复杂的指令,而是将其分解为多个小而专注的步骤。每一步都由一个 LLM 处理,而上一步的输出则直接作为下一步的输入。

📌 适用场景:
- 任务逻辑清晰,呈线性顺序。
- 每一步都以前一步的输出为基础进行构建。
- 需要在整个流程中维持上下文并逐步细化信息。
- 注重输出质量甚于执行速度的场景。
- 需要分步构建解决方案的问题 (例如:先总结、再提炼、后分类)。
❓ 为什么要使用链式工作流:
- 更高准确性:每一步都只专注于做好一件事,效果自然更好。
- 更易于调试:流程清晰,一旦出错,能快速定位问题环节。
- 更强可维护性:修改或扩展单个步骤变得简单,互不影响。
- 更可预测的结果:清晰的流程使得最终产出更加稳定一致。
具体实践:博客文章生成器
下面,我将通过构建一个 博客文章生成器 的简单示例让大家更好地理解链式工作流模式。这个示例的主要功能:根据一个给定的主题,自动生成一篇结构完整、内容丰富的博客文章。
在这里,我将整个的链路分解为以下几个步骤:
- 研究阶段:围绕主题生成核心要点。
- 结构阶段:基于要点构建文章大纲。
- 内容阶段:根据大纲撰写完整的博客正文。
- 润色阶段:对博客的正文内容进行进一步润色优化,提升文章可读性。
首先,为项目添加必要的依赖和配置,我使用的是JDK17和spring boot3.5。(注意:spring ai需要JDK17以上版本)
步骤一:添加 Maven 依赖
将以下依赖项添加到 pom.xml
文件中:
xml
<dependencies>
<!-- Spring Boot Web for building RESTful web services -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- OpenAI Model Support -- configureable for various AI providers (e.g. OpenAI, Google Gemini) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- Spring AI bill of materials to align all spring-ai versions -->
<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>
这里是部分关键的pom依赖项,配置说明如下:
spring-boot-starter-web:
用于构建RESTful API 风格的Web 应用。spring-ai-starter-model-openai:
提供了与 OpenAI API 的集成能力 ,它包含了用于调用 AI 的ChatClient
以及便捷的自动配置功能。spring-ai-bom
:
dependencyManagement
部分通过引入 Spring AI 的BOM,确保了各个 Spring AI 组件之间的版本兼容性。这样就无需手动为每个 Spring AI 构件指定版本,BOM 会自动帮你搞定版本对齐,避免冲突。
步骤二:配置应用属性
使用 application.yml
添加LLM相关的设置,这部分配置主要用于通过 Spring AI 的 OpenAI starter 与 Google Gemini 模型进行集成(也可以换成其他的模型,比如DeepSeek、Qwen,只需要替换对应的url、model和api key即可):
yaml
spring:
application:
name: spring-ai-chain-workflow
# AI configurations
ai:
openai:
api-key: ${GEMINI_API_KEY}
base-url: https://generativelanguage.googleapis.com/v1beta/openai
chat:
completions-path: /chat/completions
options:
model: gemini-2.5-flash
在这个示例中,我使用的是Google 的 gemini-2.5-flash 版本,可以在Google AI studio的网址 aistudio.google.com/app/apikey 申请免费的API KEY,每日有一定的免费额度。
步骤三:实现链式工作流的核心处理逻辑部分
现在,我们来创建链式工作流的核心类 BlogPostChainWorkflow,它将通过一个 for
循环来依次执行每一步:
vbnet
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Service
public class BlogPostChainWorkflow {
private final ChatClient chatClient;
private final String[] systemPrompts;
/**
* Constructor that initializes our ChatClient and sets up the chain prompts
* Spring will automatically inject the ChatClient.Builder
*/
public BlogPostChainWorkflow(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
this.systemPrompts = initializeChainPrompts();
}
/**
* Main method that processes a topic through our 4-step chain using a for loop
* Each step's output becomes the input for the next step in the chain
*/
public String generateBlogPost(String topic) {
String response = topic; // Start with the user's input topic
// Process through each step in our chain sequentially
for (int i = 0; i < systemPrompts.length; i++) {
System.out.println("Processing Step " + (i + 1) + ": " + getStepName(i));
// Combine the current step's prompt with the previous step's output
String input = String.format("%s\n\nInput: %s", systemPrompts[i], response);
// Send to AI and get the response for this step
response = chatClient.prompt(input).call().content();
System.out.println("Completed Step " + (i + 1));
}
return response; // Return the final processed result
}
/**
* Initialize our 4-step chain with specific prompts for each phase
* Each prompt is designed to take the previous step's output and refine it further
*/
private String[] initializeChainPrompts() {
return new String[]{
// Step 1: Research Phase - Generate key points and insights
"""
You are a research assistant. Given a topic, generate 5-7 key research points
that would be important to cover in a comprehensive blog post. Focus on:
- Current trends and developments
- Common challenges or problems
- Best practices and solutions
- Real-world applications
Format your response as a numbered list with brief explanations for each point.
Topic to research:
""",
// Step 2: Structure Phase - Create a logical outline
"""
You are a content strategist. Based on the research points provided,
create a detailed blog post outline with:
- Compelling title
- Introduction hook
- 4-6 main sections with subpoints
- Conclusion that ties everything together
Format as a clear outline with headers and bullet points.
Research points to structure:
""",
// Step 3: Content Phase - Write the full blog post
"""
You are an expert technical writer. Using the outline provided,
write a complete, engaging blog post (800-1200 words) that:
- Has a compelling introduction that hooks the reader
- Explains concepts clearly for beginners
- Uses practical examples and analogies
- Includes actionable insights
- Has smooth transitions between sections
- Ends with a strong conclusion
Write in a conversational yet professional tone.
Outline to expand:
""",
// Step 4: Polish Phase - Enhance readability and engagement
"""
You are an editor specializing in technical content. Review and improve
the blog post by:
- Adding engaging subheadings
- Including relevant analogies or metaphors
- Improving readability and flow
- Adding a compelling call-to-action
- Ensuring the tone is beginner-friendly but authoritative
Return the polished, final version.
Blog post to polish:
"""
};
}
/**
* Helper method to get descriptive names for each step (used for logging)
* This makes it easier to track which step is currently being processed
*/
private String getStepName(int stepIndex) {
return switch (stepIndex) {
case 0 -> "Research Phase";
case 1 -> "Structure Phase";
case 2 -> "Content Creation Phase";
case 3 -> "Polish & Enhancement Phase";
default -> "Unknown Step";
};
}
}
我在这里对上述代码做出相应的解析:
-
核心目的与关键组件:
BlogPostChainWorkflow
这个Service类的作用是通过一个连续的多步骤链式工作流,自动化地创建博客文章。它通过 Spring AI 提供的ChatClient
与大语言模型 (LLM) 交互。 -
构造函数:初始化客户端与提示词
构造函数负责工作流的初始化。它通过 Spring 自动注入的
ChatClient.Builder
来创建一个可复用的ChatClient
实例。同时,它会调用initializeChainPrompts()
方法,加载一个预设好的提示词 (Prompt) 数组,数组中的每个提示词都定义了博客生成过程中的一个特定阶段。 -
核心链式逻辑 (generateBlogPost 方法):
generateBlogPost(String topic)
方法是整个工作流的关键部分。它接收一个初始主题,然后按照systemPrompts
数组中定义的顺序,一步步地进行处理。- 迭代处理: 通过一个
for
循环遍历每一个处理步骤。 - 动态构建输入: 在每一步中,都将当前步骤的系统提示词与上一步的输出结果相结合,构成一个新的输入,发送给 LLM。
- 与 LLM 交互: 使用
chatClient.prompt(input).call().content()
将构建好的输入发送给 LLM 并获取返回结果。 - 输出作为下一次输入: 当前步骤从 LLM 获取的响应会更新
response
变量,作为链中下一步的输入。 - 最终结果: 所有步骤执行完毕后,方法返回经过层层加工的最终版博客文章。
- 迭代处理: 通过一个
-
提示词定义 (initializeChainPrompts 方法):
这个private的辅助方法定义了链路中每个阶段给 LLM 的具体指令 (即system prompt)。每一步都建立在上一步输出的基础上:研究、构思大纲、撰写内容和最终润色。
-
日志工具 (getStepName 方法):
根据步骤索引返回一个对应的步骤名称 (例如,为步骤 0 返回"研究阶段")。主要用于在控制台打印日志,方便我们跟踪工作流的执行进度。
步骤四:创建API入口Controller
现在,我们创建一个 REST Controller来暴露 API 接口,外部可以通过调用这个接口来生成博客文章:
kotlin
import com.bootcamptoprod.service.BlogPostChainWorkflow;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/blog")
public class BlogPostController {
private final BlogPostChainWorkflow chainWorkflow;
/**
* Constructor injection - Spring automatically provides our workflow service
*/
public BlogPostController(BlogPostChainWorkflow chainWorkflow) {
this.chainWorkflow = chainWorkflow;
}
/**
* Main endpoint to generate blog posts using our chain workflow
* Accepts a topic as request body and returns the complete generated blog post
*/
@PostMapping("/generate")
public String generateBlogPost(@RequestBody String topic) {
return chainWorkflow.generateBlogPost(topic.trim());
}
}
BlogPostController 负责处理外部请求并返回结果,监听指向 /api/blog/generate
的 POST 请求。当收到包含博客主题的请求时,该控制器会接收该主题,将其交给 BlogPostChainWorkflow
服务进行处理,然后将服务生成的完整博客文章作为 HTTP 响应返回。
链式工作流是如何一步步运作的
我们来完整地追踪一下,当提交主题 "Docker 入门指南" 后,整个流程是怎么一步步执行的。 通过以下命令启动应用,把your_gemini_api_key替换成你真实的API KEY。
ini
GEMINI_API_KEY=your_gemini_api_key mvn spring-boot:run
在这里,我通过http调试工具发送请求,发送的主题为 docker入门指南:
步骤 1: 研究阶段 (i=0)
该步骤中的System prompt是 systemPrompts[0]
的"研究助理"提示词。 请求LLM的完整prompt为systemPrompts[0]
+ "Docker 入门指南";然后LLM会分析主题,生成关键的研究要点。以下为LLM在这一步的输出示例:
markdown
1. Docker 基础与容器化概念
2. 各主流操作系统的安装流程
3. 新手必会的关键 Docker 命令
4. 创建与管理容器
5. Docker 镜像的使用
6. 常见应用场景与优势
7. 常见问题排查方法
步骤 2: 大纲阶段 (i=1)
该步骤中的System prompt是 systemPrompts[1]
定义的提示词。请求LLM的完整prompt为systemPrompts[1]
+ 步骤 1 产出的研究要点;然后LLM根据要点,创建一篇逻辑清晰的博客大纲。LLM输出示例如下:
css
标题:"Docker 揭秘:通往容器化成功的全方位指南"
I. 引言
- 开篇:为什么容器化如此重要
- 本文导读
II. 什么是 Docker?
- 容器化技术解析
- Docker 与虚拟机的比较
III. 安装指南
- Windows 安装
- Mac 安装
- Linux 安装
IV. 核心 Docker 命令
- 容器基本操作
- 镜像管理
V. 你的第一个容器
- 手把手实例教学
- 常见误区提醒
VI. 总结
- 下一步学习建议
- 更多参考资源
步骤 3: 内容创作阶段 (i=2)
该步骤中的System prompt是 systemPrompts[2]
的"博客内容创作"prompt。请求LLM的完整prompt为systemPrompts[2]
+ 步骤 2 中输出的大纲内容;然后LLM将大纲扩展成一篇完整的博客文章。这一步LLM会输出一篇 800-1200 字的完整博文。
步骤 4: 润色与增强阶段 (i=3)
该步骤中的System prompt是 systemPrompts[3]
的"最终润色"prompt。请求LLM的完整prompt为systemPrompts[3]
+ 步骤 3 中输出的博客全文。LLM会对博客文章内容进一步润色提升文章的可读性,并输出最终打磨完成的博文。

最后输出完整的blog内容
注意事项
在应用链式工作流模式时,需要注意以下几个关键点:
- 延迟 (Latency): 链条中的每一步都会增加总处理时间。对于非常长的链条,延迟会很高,可以采用异步的方式请求。
- 错误处理 (Error Handling): 当链路执行过程中的某一步失败或产生了非预期的输出时,需要设计稳健的错误处理机制,考虑加入重试或回退逻辑。
- 提示词工程 (Prompt Engineering): 预设的系统提示词质量是最终生成内容质量保障的关键。一个措辞不佳、定义不清晰的提示词可能会引发连锁反应,导致后续所有步骤的结果都不理想。
- 成本 (Cost): 链路中的每一次 LLM 调用通常都会产生费用。链条越长,意味着调用次数越多,消耗的Token数量越多。
- 上下文管理 (Context Management): 必须确保前序步骤的必要上下文能被有效传递给后续步骤。传递过多无关上下文可能会迷惑 LLM,而传递太少则可能导致信息断层。
- 复杂性 (Complexity): 链式工作流虽然分解了任务的复杂性,但当链条本身变得过长、过于复杂时,管理这条链本身也成了一件复杂的事。
写在最后
Chain workflow 模式摒弃了"一步到位"的思路,而是将复杂的任务分解为一系列更小、且环环相扣的阶段。每一步都建立在前一步的基础之上,整个流程更加有条理、灵活且易于控制。这种分步处理的方式不仅有助于产出更高质量的结果,也让我们在未来修复或改进工作流的特定环节时更加便捷。
好了,今天的分享就这么多,后续会继续分享spring ai系列的相关教程,谢谢大家,有问题欢迎在评论区交流~