news 2026/10/14 15:55:51

openJiuwen agent-core-java 工作流可视化指南:从 Workflow 到 Mermaid / PNG / SVG 的完整链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
openJiuwen agent-core-java 工作流可视化指南:从 Workflow 到 Mermaid / PNG / SVG 的完整链路
  • 人工智能
  • AI Agent
  • Agent 框架
  • 工具调用
  • Agent 工作流
  • RAG
  • MCP Clients
  • 强化学习

【免费下载链接】agent-core-java

openJiuwen agent core Java是 openJiuwen Core的 Java版本,提供AI Agent开发、运行、调优与演进相关的全套SDK能力。

项目地址:https://gitcode.com/openJiuwen/agent-core-java
点击查看免费下载

com.openjiuwen.core.graph.visualization是 agent-core-java 提供工作流可视化能力的基础包:它把工作流组件树转换成一份独立的“可绘制图”(DrawableGraph),再导出为 Mermaid 文本、PNG 或 SVG,用于开发联调、文档留档与问题排查。读完本文,你将掌握可视化包的全部 public 类型与导出入口、子图与条件分支的表示方式、expandSubgraph展开语义,以及从Workflow一行调用拿到图/文本/图片的实战方法。

一、visualization 包在项目中的定位

com.openjiuwen.core.graph.visualization包(源码位于 core/src/main/java/com/openjiuwen/core/graph/visualization)只负责“把工作流画出来”,不参与图执行引擎的调度。整个 Java 版本的可视化链路可以概括为四层:

  1. Workflow/BaseWorkflow内部维护一份实现了 HasDrawable 接口的可视化状态;
  2. HasDrawable.getDrawable()返回 Drawable;
  3. Drawable把节点、边、条件分支与循环/子工作流转换成 DrawableGraph;
  4. DrawableGraph再被导出为 Mermaid 文本,必要时继续通过渲染服务生成 PNG 或 SVG。

也就是说,Mermaid 文本、PNG、SVG 都只是同一份图结构的不同输出形式,真正的“源数据”是DrawableGraph。开发者只需面向图模型思考,输出形式可以随时切换。

二、六个 public 类型速览

可视化包对外暴露的全部 public 类型如下(API 文档见 visualization.README.md):

类型说明
Drawable将工作流组件树转换为DrawableGraph,并导出 Mermaid 文本、PNG 或 SVG 的总入口
DrawableGraph保存节点、边、开始节点、结束节点与 break 节点的图容器
DrawableNode可绘制节点的基础数据模型,包含id、展示名和元数据
DrawableSubgraphNode带嵌套DrawableGraph的节点,用于循环体和子工作流
DrawableEdge可绘制图中的一条边,支持条件边和流式边标记
DrawableBranchRouter保存条件分支的目标节点列表与展示标签

Mermaid 文本生成(MermaidDiagram)与 PNG/SVG 渲染(MermaidRenderer)由同包内非 public 的 helper 完成,本包对外只暴露上述 public 类型。

2.1 DrawableGraph:可视化数据的“源图”

DrawableGraph是承载全部可视化数据的容器(源码):

  • nodes:Map<String, DrawableNode>,节点 ID 到节点对象的映射,采用LinkedHashMap保持插入顺序;
  • edges:List<DrawableEdge>,图中全部边,保持添加顺序;
  • startNodes/endNodes/breakNodes:分别保存被标记为开始、结束与 break 的节点列表(break 节点用于子图场景)。

构造方式有两种:空构造直接创建空容器;带参构造则一次性接收节点映射、边列表和三类特殊节点列表。读取端通过getNodes()、getEdges()、getStartNodes()、getEndNodes()、getBreakNodes()访问,breakNodes还提供setBreakNodes(...)整体替换。

2.2 DrawableNode 与 DrawableSubgraphNode:普通节点与嵌套节点

DrawableNode 是最基础的节点模型,包含三个字段:

字段类型默认值说明
idString必填节点唯一标识
nameStringnull可选展示名称
metadataMap<String, Object>null节点扩展元数据

提供getId()、getName()/setName()、getMetadata()/setMetadata()等访问器。实际导出 Mermaid 时,节点文本优先使用id(源码中 Mermaid 节点内容直接取node.getId()),name与metadata保留给上层扩展使用。

DrawableSubgraphNode 继承DrawableNode,额外持有一个subgraph字段(DrawableGraph类型),表示“图包含图”。当工作流中出现循环体或子工作流时,Java 不会把它们压平处理,而是用这种嵌套结构保留层级关系——这也是expandSubgraph能按层级展开的前提。

2.3 DrawableEdge:普通边、条件边与流式边

DrawableEdge 描述一条有向边:

字段类型默认值说明
sourceString必填源节点 ID
targetString必填目标节点 ID
dataObjectnull条件边的标签或附加数据
conditionalbooleanfalse是否按虚线条件边渲染
streamingbooleanfalse是否按流式粗线渲染

在 Mermaid 导出中(见Drawable.java内部genMermaidLinks):

  • 普通边渲染为-->;
  • 条件边渲染为-.->,且data非空时输出标签|"标签"|;
  • 流式边渲染为==>,当enableAnimation为 true 时还会附加link_xxx@动画链接与animate: true属性,实现流式边“动起来”的视觉效果。

2.4 DrawableBranchRouter:分支目标与标签

DrawableBranchRouter 是条件分支的展示模型,包含两个字段:

字段类型说明
targetsList<String>条件分支可能跳转到的目标节点名列表
datasList<String>与targets对齐的展示文案或分支标签

它的数据来源是工作流层的 BranchRouter:每次调用addBranch(condition, target)时,BranchRouter.recordDrawable会把目标节点追加进targets,并把分支标签(字符串条件文本或 branchId)追加进datas,两者按位对齐。getDrawableBranchRouter()方法暴露给可视化层消费。

三、组件到绘制节点的转换规则

Drawable.addNode(String nodeId, ComponentComposable component)是组件树到图模型的桥接方法(源码),按组件类型分派:

组件类型转换结果
LoopComponent取其循环组(getLoopGroup().getDrawable())的子图,创建DrawableSubgraphNode,补齐子图结束节点并添加条件自环
AdvancedLoopComponent取其循环体(getBody().getDrawable())的子图,同样创建子图节点 + 条件自环
SubWorkflowComponent取内部子工作流(getSubWorkflowInternal().getDrawable())的子图,创建DrawableSubgraphNode
BranchComponent创建普通节点,并通过其router()添加条件边集合
IntentDetectionComponentImpl创建普通节点,并通过其router()添加条件边集合
其他组件仅创建包含id的普通DrawableNode

其中循环节点有一个关键处理:addLoopSubgraphNode会把节点 ID 记入loopNodes集合,之后任何以它为源节点的addEdge都会被改写成条件自环(conditional=true, streaming=false),在 Mermaid 中以虚线自环呈现循环语义。

对于分支类组件,addEdge(source, null, true, false, router)会读取DrawableBranchRouter的targets与datas,为每个分支目标生成一条带标签的条件边——这就是分支图在页面上“一根虚线连到多个目标”的来源。对于无法直接从路由对象提取目标列表的自定义对象,Drawable.TargetProvider接口(List<String> getTargets())提供了兜底扩展点。

另外,fillEndNodesIfEmpty会在子图缺少结束节点时自动补齐:统计子图内每个节点的出度,出度为 0 的节点被自动加入endNodes,保证循环体这类没有显式结束标记的子图也能正确渲染边界。

四、图构建辅助:起止节点与边

除addNode外,Drawable还提供一组图构建方法:

  • addSimpleNode(String nodeId):直接添加一个只包含id的普通节点;
  • setStartNode(nodeId)/setEndNode(nodeId)/setBreakNode(nodeId):将已存在节点标记为开始/结束/break 节点,节点不存在时分别抛出DRAWABLE_GRAPH_START_NODE_INVALID(112020)、DRAWABLE_GRAPH_END_NODE_INVALID(112021)、DRAWABLE_GRAPH_BREAK_NODE_INVALID(112022)对应异常(见 StatusCode);
  • addEdge(source, target):默认非条件、非流式添加普通边;
  • addEdge(source, target, conditional, streaming, data):支持Stringifiable负载数据、BranchRouter分支路由、TargetProvider自定义目标三种data形态。

被标记为开始/结束节点的普通节点在 Mermaid 中会以圆角形状(round-edge,即id(...)语法)渲染,普通节点为方角(id[...]),便于一眼识别入口与出口。

五、导出能力:Mermaid 文本、PNG 与 SVG

5.1 toMermaid:最基础的输出形式

Drawable提供三个toMermaid重载:

public String toMermaid(String title, int expandSubgraph, boolean enableAnimation) public String toMermaid(String title, boolean expandSubgraph, boolean enableAnimation) public String toMermaid() // 等价于 toMermaid("", 0, false)

生成的文本是标准的 Mermaidflowchart TD脚本,包含 YAML front-matter(title字段)、节点声明、子图声明与链接声明。参数要点:

  • title:图为 null 时抛出DRAWABLE_GRAPH_TO_MERMAID_INVALID;
  • expandSubgraph:int 版本要求非负,负数直接抛异常;boolean 版本把true归一化为EXPAND_ALL(即 -1,全部展开),false归一化为 0;
  • enableAnimation:控制流式边是否附带动画属性。

Mermaid 文本适合代码评审、提交 diff、文档粘贴与 issue 复现——你可以直接看出节点 ID、边方向与条件标签。

5.2 toMermaidPng / toMermaidSvg:图片渲染

public byte[] toMermaidPng(String title, int expandSubgraph) // 也有 boolean 版本 public byte[] toMermaidSvg(String title, int expandSubgraph) // 也有 boolean 版本

两者都先调用toMermaid生成文本,再交给同包内的MermaidRenderer渲染(源码)。渲染链路事实如下:

  • 使用 JDK 内置HttpClient,连接与请求超时均为 30 秒,跟随重定向;
  • Mermaid 文本以 UTF-8 编码后经 Base64 URL 编码拼入请求 URI;
  • 渲染服务地址优先级:系统属性MERMAID_INK_SERVER> 环境变量MERMAID_INK_SERVER> 默认值https://mermaid.ink;配置值必须是绝对 HTTP(S) URI 且不带 query/fragment,否则视为非法配置;
  • 失败重试:最多 3 次尝试,重试延迟按100ms × 尝试次数递增,可重试的状态码为 408、429 及全部 5xx;多次失败后抛出DRAWABLE_GRAPH_TO_MERMAID_INVALID(112043),异常信息中携带失败原因与渲染服务地址;
  • 格式差异:renderPng先请求/svg/做一次校验再请求/img/?format=png取 PNG;renderSvg返回/svg/响应体,同时也会请求/img/做格式校验,并且 SVG 导出默认开启动画语义(enableAnimation=true)。

因此,若图中有流式边,SVG 通常比 PNG 更适合展示这类连接(流式边动画只在 SVG/动画文本中体现)。由于渲染依赖远端服务,生产环境中建议配置内网可达的MERMAID_INK_SERVER,并注意网络超时与远端故障时的异常处理。

5.3 expandSubgraph 的展开语义

expandSubgraph控制子图展开层级,适合在“只看主干”与“展开全部内部结构”之间切换:

  • 0:不展开子图,子工作流或循环体作为整体节点(subgraph块)呈现;
  • 正整数 N:按层级向下展开 N 层;
  • true:尽可能完全展开所有子图(内部归一化为 -1)。

需要特别说明:Workflow.draw(...)/Workflow.drawBytes(...)这层公共入口不接受负数作为expandSubgraph调用参数(负数会抛异常),只有内部可视化实现才把true归一化为-1交给 Mermaid 导出逻辑做“全部展开”。想先核对主路径是否连对,建议从0开始;确认需要排查子图内部边关系时,再逐步提高展开层级。

六、从 Workflow 出发的实战入口

对大多数开发者而言,并不需要直接操作Drawable,入口已经挂在Workflow上(源码):

方法返回说明
workflow.draw()/draw(title)/draw(title, "mermaid", expandSubgraph, enableAnimation)String返回 Mermaid 文本
workflow.drawBytes(title, "png", expandSubgraph)byte[]返回 PNG 二进制
workflow.drawBytes(title, "svg", expandSubgraph)byte[]返回 SVG 二进制
workflow.getInternalDrawable()HasDrawable进入内部Drawable路线,拿底层图对象

注意两点:draw(..., "png"/"svg", ...)会抛出UnsupportedOperationException,图片必须走drawBytes;drawBytes只接受"png"或"svg",其他格式抛IllegalArgumentException。参数会经过规范化处理:title为 null 时归一化为空串,expandSubgraph支持Boolean或非负Number,enableAnimation仅接受Boolean,类型不符时统一抛出DRAWABLE_GRAPH_TO_MERMAID_INVALID。

一个最小可运行的衔接示例(图搭好以后先画出来再执行,排查成本通常更低):

import java.nio.file.Files; import java.nio.file.Path; // 导出 Mermaid 文本 String mermaid = workflow.draw("transfer-flow", "mermaid", 0, false); System.out.println(mermaid); // 导出 PNG(渲染依赖远端 mermaid.ink,建议先判断长度再落盘) byte[] png = workflow.drawBytes("transfer-flow", "png", 0); if (png.length > 0) { Files.write(Path.of("transfer-flow.png"), png); } // 导出 SVG(展开一层子图) byte[] svg = workflow.drawBytes("transfer-flow", "svg", 1); Files.write(Path.of("transfer-flow.svg"), svg);

这段代码体现了三个事实:

  1. draw(...)负责导出文本,而不是图片;
  2. 图片导出必须走drawBytes(...);
  3. 可视化展示的是当前已经注册好的节点与边,因此非常适合在真正执行前检查addConnection(...)、addConditionalConnection(...)、addStreamConnection(...)是否符合预期。

七、何时优先使用可视化

以下几类问题,先导出 Mermaid 往往最省时间:

  • 明明注册了组件,但执行路径与预期不一致;
  • 条件路由很多,想先确认分支标签与目标节点是否挂对;
  • 子工作流或循环体比较复杂,想先确认父子图关系;
  • 流式边与普通边混用,想确认哪些连接会走 streaming 路径。

八、当前边界与继续阅读

  • 本包只对外暴露 public 的可视化入口与图模型,MermaidDiagram、MermaidRenderer等 helper 的实现细节不在 API 承诺范围内;
  • 可视化反映的是图结构,不是运行时 trace——图执行引擎内部调度过程不在本包职责内;
  • 当前仓库未包含visualization包的直接单元测试,本文对导出行为的描述依据源码人工核对。

继续深入可阅读:

  • 实战教程:工作流可视化、构建工作流、使用组件;
  • API 文档:visualization 总览 及 Drawable、DrawableGraph、DrawableNode、DrawableEdge 等;
  • 核心源码:Drawable.java、DrawableGraph.java、Workflow.java、BranchRouter.java。
  • 人工智能
  • AI Agent
  • Agent 框架
  • 工具调用
  • Agent 工作流
  • RAG
  • MCP Clients
  • 强化学习

【免费下载链接】agent-core-java

openJiuwen agent core Java是 openJiuwen Core的 Java版本,提供AI Agent开发、运行、调优与演进相关的全套SDK能力。

项目地址:https://gitcode.com/openJiuwen/agent-core-java
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 15:54:52

计算机考研复试:八门课自整理题库的三轮复习法

简介&#xff1a;面向北京交通大学计算机考研复试与面试的备考整理&#xff0c;内容围绕复试提问场景&#xff0c;将计算机网络、计算机体系结构、操作系统、数据库等八门核心课程的高频问题与答案集中汇编。问题素材来自复习中广泛搜集的教材、真题回忆与各类复试帖子&#xf…

作者头像 李华
网站建设 2026/10/14 15:54:42

将《智能世界2030》变成技术预研清单:从趋势到工程落地

简介&#xff1a;《智能世界2030》由华为“智能世界”研究团队联合千余位行业学者共同撰写&#xff0c;面向关注前沿科技、数字化转型与企业战略的读者&#xff0c;系统描绘2030年智能社会的全景图。资源包共1个PDF文件&#xff0c;大小约73.3MB&#xff0c;已有756人学习下载。…

作者头像 李华
网站建设 2026/10/14 15:54:37

插件加载失败排查实战:从failed to load plugins到did not activate

我见过太多项目被 plugins 搞得焦头烂额。明明功能很简单&#xff0c;就是加载几个扩展模块&#xff0c;结果一到线上就报failed to load plugins web boot&#xff0c;日志里一行2 entries did not activate&#xff0c;连哪个插件出了问题都看不出来。更头疼的是&#xff0c;…

作者头像 李华
网站建设 2026/10/14 15:54:20

ISO/SAE 21434落地指南:从TARA分析到CAL等级的工程实践

简介&#xff1a;ISO/SAE 21434&#xff08;道路车辆—网络安全工程&#xff09;国际标准草案&#xff0c;由国际标准化组织与美国汽车工程师学会联合制定&#xff0c;面向汽车制造商、供应链参与者和网络安全研究人员&#xff0c;为车辆全生命周期的信息安全风险管理提供统一框…

作者头像 李华