当前位置: 首页 > ai >正文

聊聊Spring AI Alibaba的MermaidGenerator

本文主要研究一下Spring AI Alibaba的MermaidGenerator

MermaidGenerator

spring-ai-alibaba-graph/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/diagram/MermaidGenerator.java

public class MermaidGenerator extends DiagramGenerator {public static final char SUBGRAPH_PREFIX = '_';@Overrideprotected void appendHeader(Context ctx) {if (ctx.isSubGraph()) {ctx.sb().append(format("subgraph %s\n", ctx.title())).append(format("\t%1$c%2$s((start)):::%1$c%2$s\n", SUBGRAPH_PREFIX, START)).append(format("\t%1$c%2$s((stop)):::%1$c%2$s\n", SUBGRAPH_PREFIX, END))// .append(format("\t#%s@{ shape: start, label: \"enter\" }\n", START))// .append(format("\t#%s@{ shape: stop, label: \"exit\" }\n", END));}else {ctx.sb().append(format("---\ntitle: %s\n---\n", ctx.title())).append("flowchart TD\n").append(format("\t%s((start))\n", START)).append(format("\t%s((stop))\n", END));}}@Overrideprotected void appendFooter(Context ctx) {if (ctx.isSubGraph()) {ctx.sb().append("end\n");}else {ctx.sb().append('\n').append(format("\tclassDef %c%s fill:black,stroke-width:1px,font-size:xx-small;\n", SUBGRAPH_PREFIX,START)).append(format("\tclassDef %c%s fill:black,stroke-width:1px,font-size:xx-small;\n", SUBGRAPH_PREFIX,END));}}@Overrideprotected void declareConditionalStart(Context ctx, String name) {ctx.sb().append('\t');if (ctx.isSubGraph())ctx.sb().append(SUBGRAPH_PREFIX);ctx.sb().append(format("%s{\"check state\"}\n", name));}@Overrideprotected void declareNode(Context ctx, String name) {ctx.sb().append('\t');if (ctx.isSubGraph())ctx.sb().append(SUBGRAPH_PREFIX);ctx.sb().append(format("%s(\"%s\")\n", name, name));}@Overrideprotected void declareConditionalEdge(Context ctx, int ordinal) {ctx.sb().append('\t');if (ctx.isSubGraph())ctx.sb().append(SUBGRAPH_PREFIX);ctx.sb().append(format("condition%d{\"check state\"}\n", ordinal));}@Overrideprotected void commentLine(Context ctx, boolean yesOrNo) {if (yesOrNo)ctx.sb().append("\t%%");}@Overrideprotected void call(Context ctx, String from, String to, CallStyle style) {ctx.sb().append('\t');if (ctx.isSubGraph()) {ctx.sb().append(switch (style) {case CONDITIONAL -> format("%1$c%2$s:::%1$c%2$s -.-> %1$c%3$s:::%1$c%3$s\n", SUBGRAPH_PREFIX, from, to);default -> format("%1$c%2$s:::%1$c%2$s --> %1$c%3$s:::%1$c%3$s\n", SUBGRAPH_PREFIX, from, to);});}else {ctx.sb().append(switch (style) {case CONDITIONAL -> format("%1$s:::%1$s -.-> %2$s:::%2$s\n", from, to);default -> format("%1$s:::%1$s --> %2$s:::%2$s\n", from, to);});}}@Overrideprotected void call(Context ctx, String from, String to, String description, CallStyle style) {ctx.sb().append('\t');if (ctx.isSubGraph()) {ctx.sb().append(switch (style) {case CONDITIONAL -> format("%1$s%2$s:::%1$c%2$s -.->|%3$s| %1$s%4$s:::%1$c%4$s\n", SUBGRAPH_PREFIX,from, description, to);default -> format("%1$s%2$s:::%1$c%2$s -->|%3$s| %1$s%4$s:::%1$c%4$s\n", SUBGRAPH_PREFIX, from,description, to);});}else {ctx.sb().append(switch (style) {case CONDITIONAL -> format("%1$s:::%1$s -.->|%2$s| %3$s:::%3$s\n", from, description, to);default -> format("%1$s:::%1$s -->|%2$s| %3$s:::%3$s\n", from, description, to);});}}}

MermaidGenerator实现了DiagramGenerator的抽象方法

示例

  @Testpublic void testGraph() throws GraphStateException {OverAllState overAllState = getOverAllState();StateGraph workflow = new StateGraph(overAllState).addNode("agent_1", node_async(state -> {System.out.println("agent_1");return Map.of("messages", "message1");})).addNode("agent_2", node_async(state -> {System.out.println("agent_2");return Map.of("messages", new String[] { "message2" });})).addNode("agent_3", node_async(state -> {System.out.println("agent_3");List<String> messages = Optional.ofNullable(state.value("messages").get()).filter(List.class::isInstance).map(List.class::cast).orElse(new ArrayList<>());int steps = messages.size() + 1;return Map.of("messages", "message3", "steps", steps);})).addEdge("agent_1", "agent_2").addEdge("agent_2", "agent_3").addEdge(StateGraph.START, "agent_1").addEdge("agent_3", StateGraph.END);GraphRepresentation representation = workflow.getGraph(GraphRepresentation.Type.MERMAID, "demo");System.out.println(representation.content());}

输出

---
title: demo
---
flowchart TD__START__((start))__END__((stop))agent_1("agent_1")agent_2("agent_2")agent_3("agent_3")__START__:::__START__ --> agent_1:::agent_1agent_1:::agent_1 --> agent_2:::agent_2agent_2:::agent_2 --> agent_3:::agent_3agent_3:::agent_3 --> __END__:::__END__classDef ___START__ fill:black,stroke-width:1px,font-size:xx-small;classDef ___END__ fill:black,stroke-width:1px,font-size:xx-small;

小结

MermaidGenerator继承了DiagramGenerator,根据plantUML语法实现了DiagramGenerator定义的appendHeader、appendFooter、call、declareConditionalStart、declareNode、declareConditionalEdge、commentLine抽象方法。

doc

  • spring-ai-alibaba
http://www.xdnf.cn/news/3013.html

相关文章:

  • Java 核心--泛型枚举
  • 【KWDB 创作者计划】_深度解析KWDB存储引擎
  • vue elementui 去掉默认填充 密码input导致的默认填充
  • 大连理工大学选修课——机器学习笔记(8):Boosting及提升树
  • 2025年深圳杯-东三省联赛赛题浅析-助攻快速选题
  • 第四部分:赋予网页健壮的灵魂 —— TypeScript(中)
  • word模板填充导出-(支持word导出、pdf导出)
  • 抢先体验 | Qwen3 模型发布:基于 ZStack AIOS 平台极速体验
  • 第二章-科学计算库NumPy
  • 六.割草机技术总结--6.RTK定位精度分析
  • c++线程的创建
  • Qwen3 开源!深度对比 DeepSeek,一文选对模型
  • vue3数字秒转换为时分秒格式
  • 西游记2:天花乱坠,地涌金莲;说一会道,讲一会禅,三家(指儒、释、道)配合本如然;长生不老之术、七十二般变化之能以及筋斗云之法;你从何处而来,便回到何处去吧
  • Linux基础篇、第一章_01_3安装虚拟机手动安装部署Ubuntu22.04服务器
  • MySQL日志详解
  • 算法训练营第五天 | 454.四数相加II\ 383. 赎金信\15. 三数之和\ 18. 四数之和
  • 同一个路由器接口eth0和ppp0什么不同?
  • PCB入门指南:从电阻到常见电路的全解析
  • acwing背包问题求方案数
  • NOC科普一
  • 大模型——使用coze搭建基于DeepSeek大模型的智能体实现智能客服问答
  • 你的私域该大扫除了
  • 【记录】Python调用大模型(以Deepseek和Qwen为例)
  • 思维导图的快速生成
  • 某铝制品长棒材精轧线低压无源滤波装置改造案例
  • 智慧停车场升级难题:免布线视频桩如何破解三大核心痛点
  • 低版的spring boot 1.X接入knife4j
  • 批量修改文件名前后缀
  • 国内无法访问GitHub官网的问题解决