聊聊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 = '_';

  @Override
  protected 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));
    }
  }

  @Override
  protected 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));
    }
  }

  @Override
  protected 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));
  }

  @Override
  protected 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));
  }

  @Override
  protected 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));
  }

  @Override
  protected void commentLine(Context ctx, boolean yesOrNo) {
    if (yesOrNo)
      ctx.sb().append("\t%%");
  }

  @Override
  protected 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);
      });
    }
  }

  @Override
  protected 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的抽象方法

示例

复制代码
  @Test
  public 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_1
  agent_1:::agent_1 --> agent_2:::agent_2
  agent_2:::agent_2 --> agent_3:::agent_3
  agent_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

相关推荐
B站_计算机毕业设计之家2 分钟前
计算机毕业设计:Python农业数据可视化分析系统 气象数据 农业生产 粮食数据 播种数据 爬虫 Django框架 天气数据 降水量(源码+文档)✅
大数据·爬虫·python·机器学习·信息可视化·课程设计·农业
Q_Q51100828515 分钟前
python+uniapp基于微信小程序的旅游信息系统
spring boot·python·微信小程序·django·flask·uni-app·node.js
伏小白白白16 分钟前
【论文精度-2】求解车辆路径问题的神经组合优化算法:综合展望(Yubin Xiao,2025)
人工智能·算法·机器学习
鄃鳕17 分钟前
python迭代器解包【python】
开发语言·python
应用市场20 分钟前
OpenCV编程入门:从零开始的计算机视觉之旅
人工智能·opencv·计算机视觉
星域智链38 分钟前
宠物智能用品:当毛孩子遇上 AI,是便利还是过度?
人工智能·科技·学习·宠物
taxunjishu1 小时前
DeviceNet 转 MODBUS TCP罗克韦尔 ControlLogix PLC 与上位机在汽车零部件涂装生产线漆膜厚度精准控制的通讯配置案例
人工智能·区块链·工业物联网·工业自动化·总线协议
懷淰メ1 小时前
python3GUI--模仿百度网盘的本地文件管理器 By:PyQt5(详细分享)
开发语言·python·pyqt·文件管理·百度云·百度网盘·ui设计
Q_Q5110082851 小时前
python基于web的汽车班车车票管理系统/火车票预订系统/高铁预定系统 可在线选座
spring boot·python·django·flask·node.js·汽车·php
AntBlack1 小时前
虽迟但到 :盘一盘 SpringAI 现在发展得怎么样了?
后端·spring·openai