Skip to content

Diagram as Code:用 JSON 生成架构图的 AI 工作流

AI 应用 · Diagram as Code · 工作流 | 2026 年 5 月 | 约 8 分钟阅读 · 含可运行 demo

Diagram as Code:用 JSON 描述结构,把绘图交给 AI


如果你最近让 AI 帮你画过一张架构图,大概率经历过这种循环:

写一段 prompt → 等模型出图 → 不太对 → 换个说法再来一遍 → 还是不对 → 再换……

每次以为“这次能行了”,结果模型把 3 个节点画成 5 个、连线方向反了、左侧的模块莫名其妙跑到了右侧。画一张严谨结构图所花的时间,常常比想清楚这张图要表达什么还要长。

而最近画图的方式,正在被另一种链路替换:

写一段 JSON,把它扔给 AI,一次性生成整张图;要改,就只改 JSON,再生成一次。

听起来像是一个“小工具上的小变化”,但我相信它其实是个范式问题:图,从此不是“提示出来的”,而是“被定义出来的”。

下面这篇是我的整理,也带一个最小可用 demo——文末那几张图,全部是用本文描述的方式真实生成的。


一、从“AI 提示词画图”到“Diagram as Code”

真正有趣的对照,是“用一段自然语言提示模型画图” vs “用一份结构化 spec 让模型渲染图”。 把它们摆到一起,差别一眼就看到了。

如果你已经在用 AI 画图,那你大概率正在用第一种。问题来了——它够好吗?

现状 · AI 提示词画图

构思 → 写一段自然语言 prompt → 等图像模型出图 → 不对 → 换种说法 → 再出

工具代表:Midjourney / Stable Diffusion / DALL·E / GPT image / Gemini Flash Image。

这一代解决了“画”的体力,但同时暴露了一个新短板——

自然语言对结构的描述,天然不稳定。

“左边 3 个节点连到中间 1 个节点,右边再分出 2 条” 这句话, 模型可能给你画 5 个节点、箭头方向反了、连线对象错了。

对海报、插画、概念图,这种“飘”是可以接受的——甚至是优点。 但对架构图、流程图、层次图这类严谨的结构图——它远远不够。

演进 · Diagram as Code

抽象结构 → 写 JSON → AI 渲染 → 改 JSON → 再生成

关键差别:用一个机器友好的中间格式(JSON / DSL)代替模糊的自然语言,把“图的拓扑”变成可被精确描述、可被 diff、可被一致复现的结构。

把两种方式摆到一张表里:

维度AI 提示词画图Diagram as Code
表达介质一段自然语言结构化 JSON / DSL
输出可控性不稳定,容易“飘”高度可控,可重复复现
修改成本重写 prompt,再碰运气改几行 JSON,再跑一次
复用方式攒 prompt 模板schema + 参数化模板
协作方式prompt 版本管理麻烦可走 Git、可 diff、可 review
一致性靠模型当天心情靠 schema 与色板天然约束
适合场景海报、插画、概念图架构图、流程图、层次图

一句话总结:

图,不再是“随便提示一下生成的”——它是被精确定义、然后渲染出来的。

接受这一点,后面的所有变化才能讲得通。


二、JSON:设计的“中间语言”

在这个工作流里,JSON 不只是数据格式——它是一种设计表达语言

它把“一张图”拆成了三个机器可懂的维度:结构、内容、表现

把一张图拆成三个机器可懂的维度:结构 / 内容 / 表现

1. 结构 Structure

定义“图是怎么组织的”:

  • 有哪些节点
  • 节点之间是什么关系
  • 层级和流向是什么

最简单的一段 JSON,只需要 8 行:

json
{
  "nodes": [
    {"id": "A", "label": "输入"},
    {"id": "B", "label": "处理"}
  ],
  "edges": [
    {"from": "A", "to": "B"}
  ]
}

把这段 JSON 直接交给图像模型,得到的图就是下面这张——这一节的所有原理,在这张图里压成了一组“输入 → 处理”

由上面那段 8 行 JSON 直接渲染出的图

✅ 这张图是真渲染出来的,不是事先备好截图。生成方式见本文最后的“实现验证”。

2. 内容 Content

定义“图里写了什么”:标题、文案、注释、说明。 内容层是“图说了什么”,是给读者看的部分。

3. 表现 Style

定义“图长什么样”:色板、布局、字体、强调风格。 表现层只有一个目的——让结构与内容被一眼看懂

三者组合在一起,就是一张图的“完整定义”。 把这三层各自独立、再组合,你已经在做“设计的工程化”。

4. 进阶 · 当 spec 长到生产级

到这里你可能会问:真要把这套工作流用进生产,JSON 不会太单薄吗?

不会。简单的 nodes / edges 只是入门;一份要进 CTO 汇报、要进白皮书、要给监管/合规看的图,spec 会自然演化出几个“对模型友好、对协作友好”的工程模式。下面是反复用过、最关键的 5 个:

canvas:把画布显式写出来

json
"canvas": {
  "aspect_ratio": "16:9",
  "orientation":  "horizontal",
  "background":   "#F5F6F8",
  "margin":       "medium"
}

不要让模型猜横版还是竖版。一句 aspect_ratio: "16:9" 比 prompt 里堆三句形容词稳定 10 倍。

reference:用参考品代替形容词

json
"reference": [
  "麦肯锡战略架构汇报页",
  "华为企业级技术 PPT",
  "政府白皮书的体系结构图"
]

对图像模型而言,“具体参考品”比“抽象形容词”更有指向性。 “我要现代科技感” ≠ “我要某厂蓝白栅格风”。前者模型靠猜,后者模型有锚。

design_rules + avoid:正反并举,别只说“要什么”

json
"design_rules": ["strict grid", "flat 2D only", "rounded rectangles", "thin borders"],
"avoid":        ["glow", "cyberpunk", "gradient overload", "3D effects", "marketing illustration"]

经验之谈:avoid 列表往往比 design_rules 列表更重要。 你常常不是“知道自己要什么”,而是“清楚自己不要什么”——这是工程版本的 negative prompt。

color_system:命名色板,而不是到处写色值

json
"color_system": {
  "primary": "#0067C5",
  "accent":  "#F4B400",
  "muted":   "#EEF2F5",
  "border":  "#1573C9"
}

之后所有节点引用 primary / accent,而不是直接写 #0067C5改主题色只需改一处 —— 这就是设计 token,是 IaC 里“环境变量”那一套思路,搬到了图里。

⑤ 横切关注点 + 结构化注释

不是所有内容都属于某一“层”。安全、治理、可观测性、合规审查这类横切关注点,在 spec 里的优雅做法是单独成列(右侧整列 / 下方整带),而不是硬塞进某一层。

同时,在关键节点 / 块上挂一个结构化注释——叫 calloutbadgeinnovation_tag 都行——用来突出本图的叙事重点:

json
"layers": [
  { "id": "L1", "title": "数据接入", "callout": "★ 创新点 1" },
  { "id": "L2", "title": "计算编排", "callout": "★ 创新点 2" }
],
"crosscutting": {
  "title": "全链路安全",
  "position": "right_column",
  "items": ["业务安全", "模型安全", "数据安全", "合规审查"]
}

这样叙事可以独立调整(今年汇报强调创新一,明年强调创新三),而图本身不需要重画

把这 5 个模式叠在一起,你的 spec 就从“2 节点示意图”升级为“一份能进汇报材料的架构图”。 而这次升级背后——你完全没有换工具,只是 JSON 多写了几个字段

这是 Diagram as Code 真正的杠杆:复杂度可以线性增加,但工作流和工具栈始终不变。


三、为什么这不是简单提效?

如果只是“画得更快”,那这件事其实没那么重要。 真正重要的是:它换掉了你修改图的方式,也换掉了你和图的关系。

1. 从“撞运气改” → 语义级修改

过去你改图,做的是:重写 prompt换措辞再 roll 一次祈祷模型这回能听懂

现在你做的只是:

diff
-  "layout": "vertical",
+  "layout": "horizontal",
-  "theme": "light",
+  "theme": "dark",

你不再操作“图形”,而是在操作意图

这一字之差,本质上是把图纳入了和代码同样的修改层级:修改的是约束,不是结果。

2. 从“祈祷者” → 规则定义者

在 prompt 工作流里,你做的事情更像“求模型”——求它别画错、求它色调别飘、求它别把节点摆乱。 在 Diagram as Code 里,角色彻底变了:

  • 你定义规则(JSON / 模板 / 色板)
  • AI 负责执行(把规则渲染成像素)

你从“求 AI 画图的人”,变成了“定义图的人”。

这不是话术。它意味着你的产出可以被复用、被参数化、被批量生成——这恰恰就是工程化的入口。

3. 从一次性产物 → 可复用资产

一张图,过去是“最终结果”;现在,它变成了“可复用的结构”。

JSON 可以:

  • 像代码一样做版本管理(Git diff 看得到改了什么)
  • 沉淀成模板(同一个团队的图自然风格一致)
  • 批量生成不同变体(同一份 spec,跑出 4 种主题色板,只需替换 palette

图第一次具备了“工程属性”。


四、这个工作流适合什么场景?

不是所有图都适合用这种方式做。先承认边界,再讲优势。

适合的场景有一个共性:信息结构清晰、视觉创意要求不高

场景类型例子为什么适合
技术架构图系统模块、服务调用、数据流向本身就是节点 + 边
方法论 / 概念图认知模型、转化路径、思考框架强结构、弱视觉创意
产品 / 业务流程图用户路径、功能拆解、业务闭环信息结构稳定
状态机 / 决策树审批流、风控规则、对话流拓扑天然适合 JSON

不适合的也很明确:品牌海报、艺术插图、情绪表达型视觉。这些靠“感觉”,不靠“结构”。再好的 prompt,也不能替代设计师对张力、节奏、情绪的判断。

把这条边界提炼成一句话:

过度结构化,会损失表达的“感觉”。

记住它,这个工作流就只会增益,不会反噬。


五、它真正改变的三件事

提效只是表象。真正改变的是协作方式和组织产出。

1. 降低表达门槛

你不再需要掌握复杂的设计工具。 你只需要一件事——能够清晰地结构化表达。

如果你能把一个想法说成“它有 3 个阶段、每个阶段有 2 个输入、最后汇合到 1 个输出”, 那这张图你已经会画了——你只是还没把它写成 JSON 而已。

2. 提高团队一致性

当团队共享同一套模板:

  • 风格天然统一(色板写在 spec 里)
  • 输出自动标准化(一份 schema 约束所有图)
  • 不再依赖“某个人的审美”(图可以 review,可以 PR)

3. 极大提升迭代速度

需求变了:不需要重画,只需要 git diff 一下 JSON,再跑一次脚本。

尤其在快速试错、频繁调整的场景——比如内部技术分享、产品早期方案、博客配图——速度差不止一个量级。


六、本质:Diagram as Code

一句话总结:这是一次“基础设施级别”的视觉表达升级。

你应该熟悉这两个名字:

  • Infrastructure as Code(IaC) — 把基础设施写成代码,Terraform 一类
  • Configuration as Code — 把配置写成代码,GitOps 一类

它们都做了同一件事:把“原本靠人手工维护的东西”塞进版本管理与自动化流水线

现在,轮到“图”自己被纳入这套体系了——这就是 Diagram as Code。

它不是一个工具,而是一种生产姿态: 你画图时的输入是 JSON、输出是 PNG,中间是一段可重复执行的脚本。


七、它还会演化到哪里?

这个方向才刚刚开始。下一步的想象空间集中在三处。

1. 从 JSON 到 DSL(领域语言)

未来不一定还要写完整 JSON。把高频结构折叠成 DSL,可能更顺手:

yaml
flow:
  - 焦虑 → 分析 → 重构 → 增长

一行 DSL,语义已经够 AI 渲染:

一行 DSL 喂给 AI,渲染出“焦虑 → 分析 → 重构 → 增长”四节点流程

这张图不是 prompt 蒙出来的——它是上面那一行 DSL,经过文末的脚本生成的。

2. 从“写结构”到“生成结构”

再往前一步,JSON 自己也不需要你写——你只需要描述意图:

“描述一个从焦虑到价值重构的过程,4 个阶段,横向布局。”

链路就变成:自然语言 → LLM 生成 JSON → 图像模型渲染图

这条链路,现在已经能跑了。短板只在两处:JSON schema 的稳定性图像模型对 schema 的服从度

3. 从静态图到动态图

把 JSON 接到实时数据上,图就不再是“快照”,而是“界面”:

  • 架构图实时反映服务拓扑
  • 流程图随流量自动高亮关键路径
  • 指标卡片自动刷新数字

那一刻,Diagram as Code 就和可观测性合并了


八、实现验证 · 一个最小可用的端到端 demo

这一节是文章的“工程闭环”:前面所有的论点,都用一段真实代码兑现一次。

我用一个 100 多行的 Python 脚本把这条链路跑通:

text
JSON spec  ──→  自然语言 prompt(由脚本翻译) ──→  图像生成 API  ──→  PNG

脚本只做三件事:

  1. 解析 JSON——把 nodes / edges / style / canvas / reference / avoid / color_system 这些字段读出来;
  2. 翻译成图像 prompt——按一套固定模板把字段拼成约束严格的自然语言(标题、画布、布局、色板、节点列表、edge 列表、设计规则、避免项……);
  3. 调一次图像 API,写出 PNG——OpenAI 直连走 /v1/images/generations;OpenRouter 走 /v1/chat/completions,并声明图像 modalities。

怎么跑

把脚本和示例 JSON 放在任意目录里,配一个 .env,然后:

bash
# 单图渲染
python json_to_diagram.py render \
  --input  examples/simple-flow.json \
  --output out/simple-flow.png

# 批量(目录里所有 *.json 都会跑一遍)
python json_to_diagram.py batch \
  --in-dir  examples \
  --out-dir out

后端选择由 .env 控制——脚本同时支持两条路径:

路径模型示例API 端点何时启用
OpenRouteropenai/gpt-5.4-image-2/v1/chat/completions配置 LLM_API_KEYIMAGE_MODEL/
OpenAI 直连gpt-image-1/v1/images/generations配置 OPENAI_API_KEYIMAGE_MODEL 不含 /

本文配图由 OpenRouter 调用 openai/gpt-5.4-image-2 生成。换 google/gemini-3.1-flash-image-preview 等其它 提供商/模型 同理。

一份完整 JSON spec 长什么样

下面是文末那张“焦虑 → 增长”图对应的完整 spec(节选):

json
{
  "title": "从焦虑到价值重构",
  "subtitle": "DSL 一行声明 · AI 一次渲染",
  "type": "flow",
  "style": {
    "layout": "horizontal",
    "theme":  "light",
    "palette": ["#F59E0B", "#EF4444", "#3B82F6", "#10B981"]
  },
  "nodes": [
    {"id": "S1", "label": "焦虑 Anxiety"},
    {"id": "S2", "label": "分析 Analyze"},
    {"id": "S3", "label": "重构 Reframe"},
    {"id": "S4", "label": "增长 Growth"}
  ],
  "edges": [
    {"from": "S1", "to": "S2"},
    {"from": "S2", "to": "S3"},
    {"from": "S3", "to": "S4"}
  ]
}

这份 spec 被脚本翻译成一段约束严格的图像 prompt,然后交给图像模型,最终输出 PNG。

整条链路加起来:1 份 JSON · 1 个脚本 · 一次调用 · 1 张图。本地读 JSON、拼 prompt、写盘通常只要几秒;云端生图单次常见 约 1~3 分钟

想自己复现? 把上面这段 JSON 存成文件,执行 python json_to_diagram.py render --input <你的 json> --output out.png,就完成了一次“Diagram as Code”。


结语

这个工作流的真正意义,不在于“画图更快”,而在于:

把视觉表达,从一段不稳定的提示词,转化为可被精确定义、被一致复现的结构。

当图可以被描述、被修改、被复用,它就不再只是“展示工具”,而成为一种可编排资源——和代码、配置、数据一样,可以进 Git、进流水线、进自动化。

这才是 AI 真正介入之后,最值得关注的变化。