1. 项目概述:用Spring AI和easyui模拟ComfyUI工作流
去年第一次接触ComfyUI时就被其节点式工作流设计惊艳到了。作为Stable Diffusion的高级操作界面,它通过可视化连线的方式实现了复杂AI绘画流程的编排。最近在开发企业级AI应用时,我尝试用Spring Boot+AI框架配合前端easyui,实现了一个轻量级的ComfyUI式工作流引擎。这个demo虽然只实现了最基础的节点连接和参数传递功能,但已经能够清晰展示大模型工作流的核心设计思想。
这个方案特别适合需要快速验证AI业务流程的场景。相比直接使用ComfyUI,我们的实现有以下优势:
- 完全基于Java技术栈,与现有Spring体系无缝集成
- 前端采用轻量级easyui,比React/Vue更易快速开发
- 工作流定义可持久化到数据库,方便版本管理
- 支持与企业现有系统深度集成
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 核心组件选型
后端技术栈:
- Spring AI 2.0:作为大模型交互的核心框架,提供了标准化的API接口
- Spring Boot 3.x:基础应用框架
- JDK 17+:利用Records等新特性简化DTO定义
前端技术栈:
- easyui 1.10:提供拖拽式界面组件
- jQuery 3.6:基础DOM操作
- jsPlumb 2.15:节点连接可视化库
提示:Spring AI 2.0相比1.x版本在流式响应处理上有重大改进,特别适合需要实时显示生成过程的场景。
2.2 与ComfyUI的架构对比
| 特性 | ComfyUI | 本方案 |
|---|---|---|
| 技术栈 | Python+React | Java+easyui |
| 部署方式 | 本地运行 | 可容器化部署 |
| 扩展性 | 通过插件扩展 | 通过Spring Bean扩展 |
| 工作流存储 | 本地JSON文件 | 数据库存储 |
| 多用户支持 | 有限 | 完善的多租户支持 |
3. 核心功能实现
3.1 工作流节点设计
我们定义了四种基础节点类型:
java复制public interface WorkflowNode {
String getId();
NodeType getType(); // ENUM: INPUT, PROCESS, OUTPUT, CONTROL
Map<String, Object> execute(Map<String, Object> inputs);
}
// 示例实现 - 文本生成节点
public class TextGenerationNode implements WorkflowNode {
private final ChatClient chatClient;
@Override
public Map<String, Object> execute(Map<String, Object> inputs) {
String prompt = (String) inputs.get("prompt");
String generatedText = chatClient.call(prompt);
return Map.of("text", generatedText);
}
}
3.2 前端连线实现
使用jsPlumb实现节点连接的核心代码:
javascript复制function connectNodes(sourceId, targetId) {
jsPlumb.connect({
source: sourceId,
target: targetId,
anchors: ["Right", "Left"],
connector: ["Flowchart", { stub: 40 }],
endpoint: "Dot"
});
// 保存连接关系到后端
$.post('/api/workflow/connect', {
workflowId: currentWorkflow,
source: sourceId,
target: targetId
});
}
3.3 工作流引擎设计
核心执行逻辑采用责任链模式:
java复制public class WorkflowEngine {
private final Map<String, WorkflowNode> nodes;
public void execute(String startNodeId) {
WorkflowNode current = nodes.get(startNodeId);
Map<String, Object> context = new HashMap<>();
while (current != null) {
context = current.execute(context);
current = getNextNode(current.getId());
}
}
private WorkflowNode getNextNode(String nodeId) {
// 从数据库查询后续节点
return nodeRepository.findNextNode(nodeId);
}
}
4. Spring AI集成实践
4.1 模型配置示例
application.yml中的关键配置:
yaml复制spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
model: gpt-4-turbo
temperature: 0.7
4.2 流式响应处理
实现SSE(Server-Sent Events)推送:
java复制@GetMapping("/generate-stream")
public SseEmitter generateStream(@RequestParam String prompt) {
SseEmitter emitter = new SseEmitter();
chatClient.stream(prompt)
.subscribe(
content -> emitter.send(content),
emitter::completeWithError,
emitter::complete
);
return emitter;
}
5. 常见问题与解决方案
5.1 节点执行顺序错乱
现象:节点没有按照连线顺序执行
排查步骤:
- 检查数据库
workflow_edges表中的连接关系 - 验证
getNextNode方法是否正确返回后续节点 - 在节点执行时打印调试日志
解决方案:添加拓扑排序验证
java复制public void validateWorkflow(List<String> nodeIds) {
// 实现拓扑排序算法
if(hasCycle(nodeIds)) {
throw new IllegalStateException("工作流存在循环依赖");
}
}
5.2 大模型响应超时
优化方案:
- 设置合理的超时时间
yaml复制spring:
ai:
openai:
chat:
options:
timeout: 30s
- 实现断点续执行功能
- 添加进度状态保存机制
6. 扩展与优化方向
在实际项目中,我们进一步扩展了以下功能:
- 节点模板市场:允许用户导入预定义的节点模板
java复制public interface NodeTemplate {
String getCategory();
WorkflowNode createInstance();
}
- 版本控制:使用Git-like机制管理工作流版本
sql复制CREATE TABLE workflow_versions (
id BIGINT PRIMARY KEY,
workflow_id BIGINT,
snapshot JSONB,
created_at TIMESTAMP
);
- 性能监控:添加Prometheus指标收集
java复制@Timed(value = "node.execution.time", description = "节点执行耗时")
public Map<String, Object> executeNode(WorkflowNode node) {
// 执行逻辑
}
这个demo虽然精简,但已经包含了可视化AI工作流的核心要素。我在实现过程中最大的体会是:节点之间的参数传递定义要尽可能宽松,使用Map<String, Object>比严格定义DTO更灵活,这在快速迭代阶段特别重要。
