2026山东大学软件学院项目实训(九)——AI工作流
目录
团队信息
-
组号:69 组
-
项目:AI 零代码应用生成平台
-
负责人:樊伟彤
-
成员:者亚杰、蒋宇轩、张旭、李重昊
一、本期核心任务
本期我们将为 AI 零代码应用生成平台引入一个全新的技术架构 —— AI 智能体工作流,通过 LangGraph4j 框架重构代码生成逻辑,并补充搜集图片素材、代码质量检查等过程,让生成的网站更真实可靠。 本节主要内容如下:
-
工作流方案选型
-
LangGraph4j 入门
-
核心工作流开发
-
LangGraph4j 工作流特性实战
二、需求分析
目前生成的网站内的图片都是随机占位图片,实际上可以根据网站类型补充素材图片,让生成的网站更真实。如果想快速实现这个需求,其实只需要提供给 AI 图片搜索工具就好,交给框架和 AI 来决定什么时候调用工具,自动执行。
但是,对于可标准化的工作流程(搜集图片是在生成网站前的固定步骤),不要交给 AI 来自主判断,这样可以减少随机性和误差,而且还可以自主对流程进行新增、编排和优化。因此,我们决定基于工作流来实现。
三、工作流方案选型
方案一:
为了实现 AI 工作流,我们可以考虑市面上很多现成的平台,像 Dify、Coze、阿里云百炼,通过拖拽式的界面就能快速搭建工作流,上手简单、能够快速看到效果,非常适合快速验证想法或者让非技术人员参与构建流程。但是,当涉及到复杂的业务逻辑时,“低代码平台” 可能无法满足我们的定制化需求,尤其是当系统需要与现有的业务逻辑深度集成时。
方案二:
LangGraph4j这样的工作流编程框架虽然需要一定的学习成本,但它提供了完全的控制能力。对于我们这个项目来说,既要与现有的 Spring Boot 系统深度集成,又要处理图片收集、AI 代码生成、质量检查等复杂的业务逻辑,选择 LangGraph4j 会更加合适。
更重要的是,LangGraph4j 作为一个专门为 Java 生态设计的工作流框架,和 LangChain4j 兼容性很好,能够无缝融入我们现有的技术栈,可以直接复用项目中已有的 Service、配置和工具类,不需要从 0 进行开发。同时,它还提供了丰富的高级特性,比如条件边、循环执行、并发处理等,让我们能够构建出智能化的工作流程。
还有一点就是编程框架的可维护性和可扩展性,随着业务的发展,我们的工作流可能会变得越来越复杂,编程框架能够更好地支持这种迭代。
最后,我们选择LangGraph4j编程框架。
四、LangGraph4j入门
https://langgraph4j.github.io/langgraph4j/features/
这是langgraph4j的官方特性文档,大家也可以学习一下。
讲解了:StateGraph、AgentState、Nodes工作节点、Edges边、Checkpoints检查点
此外大家可以了解一些高级特性,如:
Streaming异步和流式处理、可视化、Parallel Branch并发、Sungraphs子图(直接添加,编译添加,操作节点)、Breakpoints断点
五、核心工作流开发
(一)、开发步骤
工作流开发的核心是:节点 + 边 + 状态 + 其他特性 具体步骤:
-
定义工作流结构(所有工作节点先只是临时输出、也无需记录状态)
-
定义状态
-
定义工作节点,先通过假数据模拟状态流转
-
开发真实的工作节点
-
工作流中使用节点,提供完整的工作流服务
(二)、定义工作流结构
根据我们的需求梳理出工作流程:
-
输入原始 Prompt
-
获取图片素材 Agent:通过工具调用从不同的渠道获取图片
-
内容图片:pexels 网页搜索
-
插画图片:undraw 抓取
-
画架构图:文本绘图 + 上传到 COS
-
Logo 等设计图片:AI 生成或者 MCP
-
提示词增强:关联图片内容到原始提示词
-
智能路由 Agent:选用哪种模式生成网站?
-
原生 HTML
-
原生多文件
-
Vue 工程
-
网站生成 Agent:利用搜集到的图片,根据上一步确认的生成模式来生成网站
-
项目构建器:文件保存 / 打包构建
图示:
有了详细的工作流程描述后,可以利用 AI,根据 LangGraph4j 的官方文档和示例,快速生成基础的工作流结构代码,比如下列提示词:
帮我生成 LangGraph4j 工作流的代码
工作流的流程描述
// ... 补充具体的流程
1. 输入原始 Prompt
2. 获取图片素材 Agent:通过工具调用从不同的渠道获取图片
3. 内容图片:pexels 网页搜索
4. 插画图片:undraw 抓取
5. 画架构图:文本绘图 + 上传到 COS
6. Logo 等设计图片:AI 生成或者 MCP
7. 提示词增强:关联图片内容到原始提示词
8. 智能路由 Agent:选用哪种模式生成网站?
9. 原生 HTML
10. 原生多文件
11. Vue 工程
12. 网站生成 Agent:利用搜集到的图片,根据上一步确认的生成模式来生成网站
13. 项目构建器:文件保存 / 打包构建
要求
先生成基础的工作流结构代码,每个工作节点中只输出一句信息就够了,不用真正实现具体的业务逻辑。
参考信息
官方文档: @https://langgraph4j.github.io/langgraph4j/core/low_level/
示例工作流实现: @https://github.com/langgraph4j/Langgraph4j-examples/blob/main/langchain4j/adaptive-rag/src/main/java/dev/langchain4j/adaptiverag/AdaptiveRag.java
得到简化版的工作流结构代码如下,存放到 langgraph4j 包下:
@Slf4j
public class SimpleWorkflowApp {
// 创建通用节点:仅打印日志
static AsyncNodeAction<MessageState, String> node(String message) {
return node_async(state -> {
log.info("执行节点:{}", message);
return Map.of();
});
}
public static void main(String[] args) throws GraphStateException {
// 1. 创建状态图
StateGraph<MessageState> workflow = new StateGraph<>(MessageState::new);
// 2. 添加节点
workflow.addNode("image_collector", node("获取图片素材"))
.addNode("prompt_enhancer", node("提示词增强"))
.addNode("router", node("智能路由选择"))
.addNode("code_generator", node("网站代码生成"))
.addNode("project_builder", node("项目构建"));
// 3. 连接边(顺序流程)
workflow.addEdge(START, "image_collector")
.addEdge("image_collector", "prompt_enhancer")
.addEdge("prompt_enhancer", "router")
.addEdge("router", "code_generator")
.addEdge("code_generator", "project_builder")
.addEdge("project_builder", END);
// 4. 编译工作流
CompiledGraph<MessageState> compiled = workflow.compile();
// 5. 可视化输出(Mermaid)
GraphRepresentation graph = workflow.getGraphRepresentation(GraphRepresentation.Type.MERMAID);
log.info("工作流图:\n{}", graph.content());
// 6. 执行流程
log.info("开始执行工作流");
int stepCounter = 1;
for (NodeOutput<MessageState> step : compiled.stream(Map.of())) {
log.info("--- 第{}步完成 ---", stepCounter++);
}
log.info("工作流执行完成!");
}
}
(三)、定义状态
需要将各个工作节点中共享的数据定义为状态。
(1)、梳理状态
| 工作步骤 | 输入状态 | 输出状态 |
|---|---|---|
| 图片收集 | originalPrompt 原始提示词 | images 图片资源列表每一个图片都应该是对象结构(图片类别、描述、地址)图片类别:content 内容图片URLsillustration 插画图片URLsarchitecture 架构图URLlogo Logo图片URL |
| 提示词增强 | originalPrompt 原始提示词 images 图片资源 | enhancedPrompt 增强后的提示词,包含图片描述和引用 |
| 智能路由 | originalPromptenhancedPrompt 增强后的提示词 | generationType 生成类型 |
| 代码生成 | enhancedPromptgenerationType 生成类型images | generatedCodeDir 生成的代码目录 |
| 项目构建 | generatedCodeDir生成的代码目录 | buildResultDir 构建成功的目录 |
(2)、定义状态类
首先定义一个自己的WorkflowContext上下文类,统一维护所有需要的字段。
还有ImageResource类,ImageCategoryEnum图片枚举类
结构如下:

(四)、定义工作节点-模拟状态流转
(1)、定义工作节点
在 langgraph4j.node 包下新建每一个步骤对应的工作节点,每个节点中只需要 Mock 一些假数据来模拟状态流转,不用真正实现业务逻辑。
包括:图片收集节点ImageCollectorNode,提示词增强节点PromptEnhancerNode,智能路由节点RouterNode,代码生成节点CodeGeneratorNode,项目构建节点ProjectBuilderNode。

(2)、工作流图应用工作节点
langgraph4j 包下新建一个 WorkflowApp,应用各个工作节点类,代码如下:
@Slf4j
public class WorkflowApp {
public static void main(String[] args) throws GraphStateException {
// 创建工作流图
CompiledGraph<MessagesState<String>> workflow = new MessagesStateGraph<String>()
// 添加节点 - 使用真实的工作节点
.addNode("image_collector", ImageCollectorNode.create())
.addNode("prompt_enhancer", PromptEnhancerNode.create())
.addNode("router", RouterNode.create())
.addNode("code_generator", CodeGeneratorNode.create())
.addNode("project_builder", ProjectBuilderNode.create())
// 添加边
.addEdge(START, "image_collector")
.addEdge("image_collector", "prompt_enhancer")
.addEdge("prompt_enhancer", "router")
.addEdge("router", "code_generator")
.addEdge("code_generator", "project_builder")
.addEdge("project_builder", END)
// 编译工作流
.compile();
// 初始化 WorkflowContext - 只设置基本信息
WorkflowContext initialContext = WorkflowContext.builder()
.originalPrompt("创建一个鱼皮的个人博客网站")
.currentStep("初始化")
.build();
log.info("初始输入: {}", initialContext.getOriginalPrompt());
log.info("开始执行工作流");
// 显示工作流图
GraphRepresentation graph = workflow.getGraph(GraphRepresentation.Type.MERMAID);
log.info("工作流图:\n{}", graph.content());
// 执行工作流
int stepCounter = 1;
for (NodeOutput<MessagesState<String>> step :
workflow.stream(Map.of(WorkflowContext.WORKFLOW_CONTEXT_KEY, initialContext))) {
log.info("--- 第 {} 步完成 ---", stepCounter);
// 显示当前状态
WorkflowContext currentContext = WorkflowContext.getContext(step.state());
if (currentContext != null) {
log.info("当前步骤上下文: {}", currentContext);
}
stepCounter++;
}
log.info("工作流执行完成!");
}
}
(3)、工作节点实现
1、图片收集节点
该节点的作用是根据用户提示词获取到网站所需的图片。 通过给 AI 提供各种不同类型的图片收集工具,来 AI 调用工具来获取网站所需的不同类型的图片,并且直接利用结构化输出特性获取到最终的图片列表。
编写内容图片收集工具,插画图片收集工具,架构图绘制工具,logo图片生成工具

AI 收集图片的提示词单独保存在资源文件image-collection-system-prompt.txt 中:
你是一个专业的图片收集助手。根据用户的网站需求,智能选择并调用相应的工具收集不同类型的图片资源。
你可以根据需要调用下面多个工具,收集全面的图片资源:
1. searchContentImages - 搜索内容相关图片,用于网站内容展示
2. searchIllustrations - 搜索插画图片,用于网站美化和装饰
3. generateArchitectureDiagram - 根据技术主题生成架构图,用于展示系统结构和技术关系
4. generateLogos - 根据描述生成Logo设计图片,用于网站品牌标识
请根据用户的需求分析,优先选择与用户需求最相关的图片类型:
- 如果涉及技术、系统、架构等内容,调用 generateArchitectureDiagram 生成架构图
- 如果需要品牌标识、Logo设计,调用 generateLogos 生成Logo
- 如果需要内容相关图片,调用 searchContentImages 搜索图片
- 如果需要装饰性插画,调用 searchIllustrations 搜索插画
你必须按照 JSON 格式输出!
然后在langgraph4j.ai包下创建图片收集AI服务ImageCollectionService,创建AI服务创建工厂ImageCollectionServiceFactory,注入指定的chatModel和各种图片收集工具;给WorkflowContext状态新增图片资源字符串字段,用于接受AI输出的图片信息。
紧接着,工作节点需要调用 AI 服务收集图片,并更新状态的 imageListStr 字段。由于目前我们的工作节点类都是通过静态方法提供工作节点的,可以写一个获取 Spring Bean 的静态工具类,就可以在静态方法中获取到 ImageCollectionService 了,这样就不用修改原本的代码。
在静态方法中获取指定 Bean:
// 获取AI图片收集服务
ImageCollectionService imageCollectionService =
SpringContextUtil.getBean(ImageCollectionService.class);
2、提示词增强节点
将获取到的图片信息拼接到原始提示词下,并在拼接提示词时引导 AI 利用这些图片信息作为网站素材。示例:
## 可用素材资源
请在生成网站使用以下图片资源,将这些图片合理地嵌入到网站的相应位置中。
- 架构图:编程学习网站架构(https://www.codefather.cn/logo.png)
- Logo图片:编程导航学习圈的 Logo(https://www.codefather.cn/logo.png)
3、智能路由节点
根据用户的原始提示词选择对应的网站生成方式,利用项目已有的AiCodeGenTypeRoutingService 实现即可,逻辑参考 createApp 方法的实现。
4、代码生成节点
首先根据代码生成类型,调用 AiCodeGeneratorFacade 生成代码,获得流式输出。然后还需要同步等待流式输出完成,将代码生成目录保存到状态中,交给下一个工作节点去处理。
5、项目构建节点
如果是 Vue 工程项目类型,调用项目已有的 VueProjectBuilder 打包构建;如果是其他类型,直接忽略(因为上一步文件已经通过 AI 工具调用保存)。
6、工作流使用工作节点
最后,将原本的 WorkflowApp 改造为一个新的工作流 CodeGenWorkflow,作为正式可用的类。不再是通过 main方法运行,而是提供执行工作流的方法。
@Slf4j
public class CodeGenWorkflow {
/**
* 创建完整的工作流
*/
public CompiledGraph<MessagesState<String>> createWorkflow() {
try {
return new MessagesStateGraph<String>()
// 添加节点 - 使用完整实现的节点
.addNode("image_collector", ImageCollectorNode.create())
.addNode("prompt_enhancer", PromptEnhancerNode.create())
.addNode("router", RouterNode.create())
.addNode("code_generator", CodeGeneratorNode.create())
//.addNode("code_quality_check", CodeQualityCheckNode.create())
.addNode("project_builder", ProjectBuilderNode.create())
// 添加边
.addEdge(START, "image_collector")
.addEdge("image_collector", "prompt_enhancer")
.addEdge("prompt_enhancer", "router")
.addEdge("router", "code_generator")
.addEdge("code_generator", "project_builder")
// .addEdge("code_generator", "code_quality_check")
// 新增质检条件边:根据质检结果决定下一步
// .addConditionalEdges("code_quality_check",
// edge_async(this::routeAfterQualityCheck),
// Map.of(
// "build", "project_builder", // 质检通过且需要构建
// "skip_build", END, // 质检通过但跳过构建
// "fail", "code_generator" // 质检失败,重新生成
// ))
.addEdge("project_builder", END)
// 编译工作流
.compile();
} catch (GraphStateException e) {
throw new BusinessException(ErrorCode.OPERATION_ERROR, "工作流创建失败");
}
}
/**
* 执行工作流
*/
public WorkflowContext executeWorkflow(String originalPrompt) {
CompiledGraph<MessagesState<String>> workflow = createWorkflow();
// 初始化 WorkflowContext
WorkflowContext initialContext = WorkflowContext.builder()
.originalPrompt(originalPrompt)
.currentStep("初始化")
.build();
GraphRepresentation graph = workflow.getGraph(GraphRepresentation.Type.MERMAID);
log.info("工作流图:\n{}", graph.content());
log.info("开始执行代码生成工作流");
WorkflowContext finalContext = null;
int stepCounter = 1;
for (NodeOutput<MessagesState<String>> step : workflow.stream(
Map.of(WorkflowContext.WORKFLOW_CONTEXT_KEY, initialContext))) {
log.info("--- 第 {} 步完成 ---", stepCounter);
// 显示当前状态
WorkflowContext currentContext = WorkflowContext.getContext(step.state());
if (currentContext != null) {
finalContext = currentContext;
log.info("当前步骤上下文: {}", currentContext);
}
stepCounter++;
}
log.info("代码生成工作流执行完成!");
return finalContext;
}
}
六、LangGraph4j工作流特性
(一)、跳过构建-条件边

(二)、质量检查-循环边
新增代码质检 Agent 工作节点,在生成代码后,检验代码是否有异常、能否正常打包,如果有异常则返回到网站生成 Agent 重新生成。 该节点所需的状态: generatedCodeDir + generationType 该节点返回的状态: qualityResult 质检结果
-
isValid 是否通过
-
errors 错误列表
-
suggestions 改进建议

开发步骤
定义数据模型
编写质量检查 AI 提示词 code-quality-check-system-prompt.txt ,提示词重点突出 检查语法错误,并且强调结构化输出的 JSON 格式。
你是一个专业的代码质量检查专家。你的任务是分析用户提供的网站代码,检查语法错误等方面的问题,确保项目可以正常
运行和打包。
## 检查重点
### 1. 语法和结构错误
- HTML 标签是否正确闭合
- CSS 语法是否正确
- JavaScript 语法错误
- 文件引用路径是否正确
- 缺失的依赖或资源
### 2. 代码质量
- 代码结构是否合理
- 命名规范是否一致
- 代码重复性检查
### 3. 功能完整性
- 页面功能是否完整
- 交互逻辑是否正确
- 响应式设计检查
## 输出格式
请严格按照以下 JSON 格式返回检查结果:
json
{
"isValid": true/false,
"errors": [
"具体的错误描述1",
"具体的错误描述2"
],
"suggestions": [
"改进建议1",
"改进建议2"
]
}
## 判断标准
- isValid = true: 代码无严重语法错误,能够正常运行和打包
- isValid = false: 存在语法错误、结构问题或其他会导致无法正常运行的问题
- errors: 必须修复的问题,如语法错误、缺失文件等
- suggestions: 关于如何修复错误和改进代码的建议
请仔细分析代码,提供专业的质量检查结果。
开发质量检查工作节点
修改代码生成节点
修改工作流
(三)、图片收集优化-并发
方案一:工作节点内部实现并发
在图片收集节点内部通过 CompletableFuture 并发调用工具进行收集,并更新结果。
方案二:利用 LangGraph4j 的并发能力
把每个图片收集工具定义成工作节点,并发执行这些工具,最后再统一汇总结果。
方案三:利用 LangGraph4j 的子图能力
把每个图片收集工具定义成子图,并发执行这些工具,最后再统一汇总结果。
图片收集规划实现
编写 AI 收集图片的提示词 image-collection-plan-system-prompt.txt :
你是一个专业的图片收集规划师。你的任务是分析用户的网站需求,制定合理的图片收集计划。
## 图片类型说明
### 1. 内容图片 (contentImageTasks)
- 用途:网站的主要内容配图
- 来源:通过关键词搜索获取
- 示例:产品图片、场景图片、人物图片等
### 2. 插画图片 (illustrationTasks)
- 用途:装饰性插画,提升页面美观度
- 来源:Undraw 插画库
- 示例:抽象插画、概念图解等
### 3. 架构图 (diagramTasks)
- 用途:展示系统架构、流程图等技术图表
- 来源:通过 Mermaid 代码生成
- 示例:系统架构图、流程图、组织结构图等
### 4. Logo图片 (logoTasks)
- 用途:品牌标识、图标等
- 来源:AI 生成
- 示例:公司Logo、产品图标等
## 规划原则
1. 需求导向:根据用户描述的网站类型和用途来规划图片
2. 适量原则:每种类型的图片数量要合理,避免过多或过少
3. 关键词精准:选择最能体现需求的关键词
4. 描述清晰:为任务提供清晰的描述说明
## 输出要求
请严格按照以下 JSON 格式返回图片收集计划:
json
{
"contentImageTasks": [
{
"query": "搜索关键词"
}
],
"illustrationTasks": [
{
"query": "插画关键词"
}
],
"diagramTasks": [
{
"mermaidCode": "mermaid图表代码",
"description": "图表用途描述"
}
],
"logoTasks": [
{
"description": "Logo设计描述,如名称、行业、风格等"
}
]
}
注意:
- 如果某种类型的图片不需要,对应数组可以为空
- 每个任务的 description 要说明图片的具体用途和位置
- mermaidCode 要是有效的 Mermaid 语法代码
- 关键词要使用中文或英文,选择搜索效果最好的语言
CompletableFuture并发实现后在图片收集节点内增加 Spring 的 StopWatch 来对比性能:


使用并发后,性能提升了几倍,缩短了 70 多秒。
Langgraph4j并发实现(未使用)

(四)、SSE流式输出
使用 SseEmitter 或者自己构造 Flux 响应式数据流,比如每次执行工作流时新建 SseEmitter,通过它来灵活控制要输出什么内容。
Flux实现
CodeGenWorkflow 工作流新增 SSE 输出版本的执行工作流方法,自己构造 Flux 响应流:
/**
* 执行工作流(Flux 流式输出版本)
*/
public Flux<String> executeWorkflowWithFlux(String originalPrompt) {
return Flux.create(sink -> {
Thread.startVirtualThread(() -> {
try {
CompiledGraph<MessagesState<String>> workflow = createWorkflow();
WorkflowContext initialContext = WorkflowContext.builder()
.originalPrompt(originalPrompt)
.currentStep("初始化")
.build();
sink.next(formatSseEvent("workflow_start", Map.of(
"message", "开始执行代码生成工作流",
"originalPrompt", originalPrompt
)));
GraphRepresentation graph = workflow.getGraph(GraphRepresentation.Type.MERMAID);
log.info("工作流图:\n{}", graph.content());
int stepCounter = 1;
for (NodeOutput<MessagesState<String>> step : workflow.stream(
Map.of(WorkflowContext.WORKFLOW_CONTEXT_KEY, initialContext))) {
log.info("--- 第 {} 步完成 ---", stepCounter);
WorkflowContext currentContext = WorkflowContext.getContext(step.state());
if (currentContext != null) {
sink.next(formatSseEvent("step_completed", Map.of(
"stepNumber", stepCounter,
"currentStep", currentContext.getCurrentStep()
)));
log.info("当前步骤上下文: {}", currentContext);
}
stepCounter++;
}
sink.next(formatSseEvent("workflow_completed", Map.of(
"message", "代码生成工作流执行完成!"
)));
log.info("代码生成工作流执行完成!");
sink.complete();
} catch (Exception e) {
log.error("工作流执行失败: {}", e.getMessage(), e);
sink.next(formatSseEvent("workflow_error", Map.of(
"error", e.getMessage(),
"message", "工作流执行失败"
)));
sink.error(e);
}
});
});
}
/**
* 格式化 SSE 事件的辅助方法
*/
private String formatSseEvent(String eventType, Object data) {
try {
String jsonData = JSONUtil.toJsonStr(data);
return "event: " + eventType + "\ndata: " + jsonData + "\n\n";
} catch (Exception e) {
log.error("格式化 SSE 事件失败: {}", e.getMessage(), e);
return "event: error\ndata: {\"error\":\"格式化失败\"}\n\n";
}
}
编写工作流执行接口后,编写一个前端网站进行测试
七、总结
我们深入学习了 AI 工作流的概念和实现。通过 LangGraph4j 框架,我们不仅重构了一套新的代码生 成逻辑,还为系统增加了智能图片收集功能,让生成的网站更加真实生动。
八、后续计划
对AI零代码平台进行性能、实时性、安全性、稳定性、成本优化
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)