LLM + SVG,能不能稳定生成技术图?我拆了 fireworks-tech-graph

最近我在看一类很有意思的仓库:它们都在讲同一件事,让大模型把系统描述直接变成图。

这类仓库的展示页通常都很容易让人心动。你输入一句“帮我画一个 RAG 架构图”或者“画一个多智能体协作流程”,很快就能得到一张看起来不错的图。问题是,展示效果是一回事,真正把这件事做成稳定工作流又是另一回事。

fireworks-tech-graph 吸引我的地方,就在这里。

我点开它,本来只是想看看“又一个 AI 画图 skill”长什么样。但真正读完之后,我的兴趣点变了:这个仓库真正值得研究的,不是它能不能把自然语言变成技术图,而是它怎么把这件事拆成一条更像工程系统、而不是纯 prompt 演出的链路。

如果先给一句很实在的判断,我会这样说:

  • 如果你只是想随手画一张草图,它未必是最轻的方案
  • 如果你想把“技术图生成”做成一条更稳定、可校验、可回归的流程,它就很值得拆

这篇文章想回答的不是“它酷不酷”,而是四个更具体的问题:

  • 这个仓库本质上是什么,不是什么
  • 它对外承诺的工作流是什么
  • 从代码和脚本看,最稳定的一条落地路径是什么
  • 这种设计真正的优点、边界和潜在问题是什么

先从一个让我改观的细节说起

我最开始有个很朴素的猜测:既然仓库里有个叫 generate-diagram.sh 的脚本,那它多半就是主生成器。

结果一翻脚本,我就被提醒了一下。这个脚本自己写得很清楚:它不负责真正生成 SVG,主要做的是两件事:

  • 校验已有的 SVG
  • 调 rsvg-convert 导出 PNG

也就是说,它更像“验收和导出层”,不是“主渲染层”。

这个细节很小,但它一下子把我从“这是个 prompt 驱动的小工具”拉到了另一个理解框架里:
也许这个仓库真正的重点,不在“让模型写出一张图”,而在“让一张图能够稳定落地、被检查、被导出”。

后来继续往下看 generate-from-template.py 和 fixtures/*.json,这个感觉就越来越强了。

为什么这类系统最后总会落到 SVG

在真正拆 fireworks-tech-graph 之前,有个背景其实值得先说一下:为什么很多技术图生成系统,最后都会落到 SVG,而不是位图,或者只停留在 Mermaid 这种 DSL 上。

因为技术图跟普通插画不一样。

你对一张“系统图、流程图、架构图”的要求,通常是这几件事:

  • 文字和线条放大后不能糊
  • 节点、箭头、图层最好能精确控制
  • 最终结果最好还能继续编辑、校验、导出

SVG 很自然地满足这些要求。它本质上是结构化文本,适合程序生成;同时又是矢量图,适合放大、导出和后续编辑。对 LLM 来说,它也比直接生成位图更“可推理”,因为节点、连线、容器、标签都可以先变成结构,再变成图形。

但 SVG 的麻烦也正好在这里。

它不是那种“只要大概对了就能糊过去”的格式。图一旦复杂起来,问题会立刻暴露出来:

  • XML 结构很脆
  • arrow marker 很容易写坏
  • 路径、坐标、层级一复杂就容易失控

所以我现在越来越觉得,真正难的通常不是“让模型说出图里有什么”,而是“怎么把这些结构稳定地落成一份不坏、可渲染、风格一致的 SVG”。我读这个仓库时,注意力也正是被这一层吸过去的。

我一开始怎么理解它,后来修正了什么

我一开始对这个仓库有三个直觉判断。

第一,我把它归类成一个“AI 画技术图的 skill 包”。
第二,我猜真正的实现核心大概率藏在某个 SVG 生成脚本里,而不是 README 或模板文件里。
第三,我怀疑它的自动布局能力不会特别强,很多结构还是要靠上游先想清楚。

后来读完源码,我发现这三个判断里有两条基本成立,一条需要修正。

成立的部分是:

  • 它确实不像一个完整产品,更像 skill + renderer + validation pipeline
  • 真正的工程核心也确实在脚本里,而不是展示文档里

需要修正的部分是:

  • 我原来会把它过快地理解成“LLM 直接把图画出来”,但更准确的说法应该是:LLM 负责更高层的语义组织,而最终 SVG 的生成和很多稳定性保障是脚本完成的

另外我还修正了一个更具体的误判:我原本会高估 templates/*.svg 的作用。最开始我以为模板文件会承载很多布局和结构,像一种比较重的模板系统;但实际看了 generate-from-template.py 以后,感觉更准确的说法是:模板在这里更轻,至少在当前实现里,主要渲染逻辑还是代码拼出来的,而不是靠模板承担大部分结构。

我是怎么研究它的

这次我没有一上来就钻进一个大脚本里,而是按下面这条路径读:

  1. 先看 README.md,理解它对外怎么描述自己
  2. 再看 SKILL.md,理解它预设的模型工作流
  3. 然后看 package.json,确认这个仓库是怎么打包和暴露入口的
  4. 最后才看 scripts/generate-from-template.py、scripts/validate-svg.sh、scripts/generate-diagram.sh 和 fixtures/*.json

这样读的好处是,你比较不容易把“用户侧承诺”和“代码侧事实”混为一谈。

另外,为了避免自己只停在静态阅读上,我还实际跑了一条最小链路:把 fixtures/mem0-style1.json 交给 generate-from-template.py 生成 SVG,再用 validate-svg.sh 校验,最后用 rsvg-convert 导出 PNG。至少到这一步,我可以确认:脚本层这条链路不是纸面上的,而是真能跑通。

这个仓库对外承诺的工作流是什么

如果只看它的 SKILL.md,这个仓库对外承诺的,是一套很典型的“模型主导”工作流:

  1. 分类图类型
  2. 从用户描述里抽结构
  3. 规划布局
  4. 加载风格参考
  5. 把节点映射到图形
  6. 检查 icon 需求
  7. 写 SVG
  8. 校验
  9. 导出 PNG
  10. 回报输出路径

这里有个很重要的判断边界:从这份 skill 文档本身看,它并没有把自己描述成“先产出 JSON、再交给渲染器”的正式接口。它更像是在教模型如何生成一张技术图,并推荐在复杂场景下结合 helper scripts 做稳定化处理。

所以如果只根据 SKILL.md 来描述它,我会更谨慎地说:

它首先是一个“引导模型生成技术图”的 skill,而不是一个单纯的 Python 图形库。

从代码看,最稳定的一条落地路径是什么

但如果继续往下看脚本和 fixtures,就会出现另一层更“工程化”的图景。

在我看来,这个仓库目前最稳定、最值得信赖的一条落地路径,其实更像这样:

结构化图数据 -> generate-from-template.py -> SVG -> validate-svg.sh -> rsvg-convert -> PNG

用图表示,大致像这样:

flowchart TD
  A["用户 / 模型整理出结构化图数据"] --> B["generate-from-template.py"]
  B --> C["生成 SVG"]
  C --> D["validate-svg.sh"]
  D --> E["rsvg-convert"]
  E --> F["导出 PNG"]

这里我故意把“用户 / 模型整理出结构化图数据”写得比较宽,是因为从当前仓库来看,这层数据既可能来自模型的中间整理,也可能来自现成 fixture,并不是一个统一暴露出来的正式 API。

这也是为什么我不想把文章写成“它的核心流程就是 JSON 渲染”。
更准确的说法应该是:

  • 从对外交互上,它是 skill 驱动的图生成工作流
  • 从脚本层实现上,它已经具备了一条结构化输入到 SVG/PNG 的稳定链路

代码里最值得看的几个点

1. 它首先是一个 skill 资源包,而不是传统应用

这一点从 package.json 就能直接看出来。main 指向的是 SKILL.md,打包文件里也主要是:

  • SKILL.md
  • README.md
  • references/
  • scripts/
  • fixtures/
  • templates/
  • assets/

这说明它首先不是一个有明确前后端边界的应用,而是一个围绕技能调用组织起来的资源包。所以如果把它理解成“一个独立可交互的画图产品”,很容易误读它真正的设计重点。

2. 真正的代码核心在 generate-from-template.py

如果只问一句“哪个文件最值得读”,我的答案还是 scripts/generate-from-template.py。

原因不是因为它“最长”,而是因为这个脚本里集中放了最关键的几类能力:

  • style profiles
  • 节点标准化
  • 箭头标准化
  • 正交路由
  • SVG 组装

尤其是 build_svg() 这一段,很能说明这个仓库到底在做什么。它不是把一个现成 SVG 模板简单填空,而是根据 style / containers / nodes / arrows / legend / footer 这些输入,逐步组装出一张完整 SVG。

如果你再对照 fixtures/mem0-style1.json 去看,会更有感觉。那个 fixture 里,containers、nodes、arrows 已经把结构写得很清楚了,例如:

  • Input Layer
  • Memory Manager (mem0 Core)
  • Storage Layer
  • Output / Retrieval

这些分层不是在渲染时“灵光一现”冒出来的,而是先被表达成结构,再被 renderer 画出来。

所以如果说这个系统有什么“可执行核心”,那它更像是一个专用渲染器,而不是单纯的模板替换器。

3. helper scripts 负责把“能生成”变成“更可用”

另一个让我印象比较深的点,是 shell 脚本的职责切分。

generate-diagram.sh 这个名字其实很容易让人误会。直觉上你会以为它是主生成器,但脚本里自己写得很清楚:真正的 SVG generation 不是它做的,它主要负责两件事:

  • 校验现有 SVG
  • 调用 rsvg-convert 导出 PNG

这个细节特别关键,因为它说明脚本层设计并不是“一根脚本走天下”,而是:

  • Python 脚本负责渲染
  • shell 脚本负责校验和导出

这类职责切分虽然不复杂,但很实用。因为一旦失败,你至少知道自己应该先查哪一层,而不是所有问题都继续回到 prompt 上。

4. fixtures 暗示了它对“稳定输入”的依赖

fixtures/*.json 是这次研究里让我改观最多的一部分。

一开始只看展示时,我会很自然地把它想成一个“自然语言一来,系统自己把图全排好”的仓库。
但看完 fixtures 以后,这个印象必须往回收。

因为在这些 JSON 里,很多信息已经很显式了:

  • node 的位置
  • 宽高
  • arrow 的元数据
  • container 的边界

这说明它在当前形态下,更像是在“稳定渲染一份已经被整理过的结构化图描述”,而不是“从零自动求解完整布局”。

这不是缺点本身,但它必须被说清楚。否则读者很容易高估它的自动化程度。

我最后真正修正了哪些理解

回头看,这次研究里我修正了 3 个关键认识。

第一,我不再把它简单理解成“AI 画图仓库”。
更准确的说法是:它是一个围绕技术图生成搭起来的 skill + 渲染器 + 校验导出链路。

第二,我不再把模板文件想得太重。
当前实现里,模板并不是主角,渲染器代码才是主角。

第三,我不再把它理解成“完全自动布局”。
从当前 fixtures 和代码路径看,它更接近“语义结构先行,渲染稳定落地”,而不是“自然语言直接自动生成最终图布局”。

这个方案真正的优点

如果只列 3 条我觉得最实在的优点,我会选这三条。

第一,它比“让模型直接输出最终 SVG / Mermaid / 图形描述结果”更可控。
因为渲染规则、风格系统和校验机制都被固化进了代码和脚本,不完全依赖模型临场发挥。

第二,它把“画图”从纯提示词问题,往工程问题推进了一步。
一旦有了 renderer、validator 和 fixtures,很多问题都能被定位、复现和回归测试,而不是永远停留在“换个 prompt 试试”。

第三,它对 AI / Agent 技术图这种高重复语义场景很友好。
因为这类图的节点和箭头语义本来就有一定模式化空间,shape vocabulary 和 arrow semantics 可以长期复用。

这个方案的边界和问题

但这套方案的边界也很清楚。

第一,它当前并不等于“真正自动布局引擎”。
你如果期待的是:给一句自然语言,它自己把复杂系统排成一张非常成熟的图,那从现有实现看,这件事还没有完全被解决。

第二,它的核心渲染逻辑集中在一个长 Python 文件里。
短期看这种集中式实现很高效,长期看图元、风格、规则继续增长以后,维护压力会越来越明显。

第三,它更像一套工程后端,而不是面向普通用户的交互式产品。
这意味着它很适合嵌进 AI 工作流或 skill 体系,但不一定天然适合作为“人人打开就能直接用”的工具。

所以,它值不值得用

如果只是问“值不值得用”,我的回答会比前面简单很多。

如果你要的是:

  • 快速画一张草图
  • 临时做个示意图
  • 不太在意后续校验和回归

那它未必是最轻的选择。

但如果你要的是:

  • 把技术图生成做成更稳定的流程
  • 希望结果能被校验、能被导出、能被重复复现
  • 你的图类型本来就带有比较强的语义模式

那这个仓库就很值得看。

它未必解决了“自动画图”的全部难题,但它至少把问题从“模型会不会灵光一现”往“系统能不能稳定落地”推进了一步。

如果继续研究,我会往哪挖

如果继续往下,我最想追两个问题。

第一个问题是:当图规模继续增大时,当前 routing 逻辑的复杂度和可维护性会不会成为瓶颈。现在这套方案在中小型技术图上是成立的,但更复杂的场景下是否还能保持干净连线,我还没有足够证据。

第二个问题是:如果它继续扩图类型和风格,单文件 renderer 会不会很快变得难以维护。
如果这个项目还要继续演化,我会很关注它是否需要把 style、shape、routing、validation 拆出更清晰的模块边界。

最后

很多人看到这类仓库时,注意力会停在“自然语言转图”这个表面能力上。
但对我来说,fireworks-tech-graph 真正值得研究的地方,不是这个结果,而是它尝试把结果背后的链路拆清楚:

  • LLM 负责较高层的语义组织
  • 渲染器负责确定性 SVG 落地