AI 画的架构图总跟真实系统对不上:文本生成图的排查与修法

2026-07-29

数据截至 2026-07,各产品的额度与报错口径以官方最新说明为准。

多数人把这件事归错了因:图对不上系统,怪的是模型不会画图。真正的断点通常在上游——你喂进去的是你记忆里的系统,不是仓库里的系统。 模型把一段有偏差的描述翻译成一张排版工整的图,偏差不会消失,只会被工整的线条盖住,然后你在评审会上把它当依据用。

换成文本语法生成图(Mermaid、PlantUML、Graphviz、D2 这类),真正的收益不是”画得快”。拖框工具画一张新图未必比写二十行文本慢。收益在改:图变成了纯文本,能进版本库,能被 diff,能在 pull request 里逐行看改了哪条边,能被脚本校验。代价也在这儿——它从此带上代码的全部毛病:过期、冲突、口径不一致。

这篇只管结构类图:架构图、时序图、流程图、状态机。站内另外两篇管别的环节——文档那篇讲文字型交付物怎么组织和更新(见 AI 写文档),设计稿转代码那篇讲从视觉稿到前端实现(见 设计稿转代码)。本篇不碰美化、不碰白板协作。

一、先判断你要哪一类图,错配是最贵的返工

返工里有相当一部分不是画错了,是画的品种不对。你说”给我画个架构图”,模型给了一张方框加箭头的部署拓扑,你想要的其实是一次请求怎么在三个服务之间流转。这两张图的信息维度完全不同,改多少遍都不会变成对方。

在开口之前,把四个问题的答案先定下来:

  • 看图的人是谁。给新同事看的入职图,粒度到”服务”就够;给做容量评估的人看,必须带上实例数与队列。
  • 图上一个方框代表什么。进程?代码模块?物理机?团队?一张图里混用两种粒度,是所有”看着别扭又说不出哪儿不对”的根源。
  • 箭头代表什么。同步调用、异步消息、数据流向、依赖关系,这四种语义在视觉上长得一样。要么分图,要么用不同线型并在图例里写死。
  • 这张图要活多久。一次性沟通的草图,画完即弃;要长期维护的,得有明确的更新触发条件。

这四条必须你来定,模型定不了——它没有你的受众,也不知道你们团队把”服务”这个词用成了什么意思。定完再让它生成,第一版的可用率会有明显差别。

二、现象与成因的判别表

图生成出来之后先别改,先归因。同一个”图不对”,成因不同,处置动作也完全不同。

现象大概率成因怎么验证处置动作
图里有仓库中不存在的服务或模块模型在补全常见架构范式,而不是读你的代码拿图上每个节点名回仓库搜;搜不到、且不属于你自己起的抽象名,就是编的改成先给它目录树和入口文件清单,再让它生成
节点名对,但调用方向反了描述里只说了”A 和 B 有关系”,没说谁发起在代码里找调用点,看是谁 import 谁、谁在发请求描述改成主谓宾句式:A 通过 HTTP 调用 B 的某接口
图渲染失败或半张图空白语法错误,多为节点 ID 含空格、中文括号、保留字把图源单独丢进渲染器跑一遍,看报错行号节点 ID 全用英文短标识,显示文字放在方括号里
图能渲染但线条互相穿插、读不了节点太多,或布局方向和信息流向不一致数一下节点数,超过十几个基本必乱拆子图,或换布局方向(自上而下改成自左向右)
改一行文字,整张图布局全变布局是算法算出来的:标签文字长度变了,节点尺寸就变,整体排布跟着重算对图源做 diff,确认这次只改了标签文字;再把标签改回原长度重渲一次,布局若复原即可确认接受布局会漂,别把布局当稳定资产;想少抖就固定节点声明顺序、控制标签长度
图和代码都对,但和上周的图不一样同一系统被不同人用不同粒度描述过比对两版图的节点粒度定义把粒度约定写进仓库的说明文件,作为生成前提
中文标签渲染成方块或问号渲染环节缺字体,不是图源的问题换成纯英文标签重渲一次,正常则确认是字体给渲染环境装中文字体,或改用带字体的渲染方式

最后一行容易被误判成图源的问题,实际上它发生在渲染环节,改图源改多少遍都没用。

三、AI 能接哪三步,哪两件必须你自己定

把这个环节拆开看,分工其实很清楚。

机器能干得比你好的三步。

第一步是语法翻译。你用大白话描述”用户请求先过网关,网关校验完转给订单服务,订单服务同步查库存、异步发消息给通知服务”,让它输出对应语法的图源。这一步机器几乎不会错,因为它是纯粹的形式转换,没有事实成分。

第二步是格式互转。同一份结构,从流程图改成时序图,从一种图语言换成另一种,从横排改成竖排。手工重画要十分钟,转换是几秒钟的事。这是文本图相对拖框最实在的优势——拖框工具里换个方向就是重画。

第三步是批量整理。十几个节点的命名风格不统一、有的带前缀有的不带、图例缺失,让它统一一遍比手工快。

必须你定的两件事。

一是边界。哪些东西上图、哪些不上,这是判断题不是检索题。第三方依赖画不画?降级链路画不画?内部的历史遗留旁路画不画?我的做法是给一张图设一个”读者能带走的三句话”,凡是不服务于这三句话的节点全部砍掉。模型不会砍,你不让它砍它就一直加。

二是事实。图上的每条边都是一句可以被证伪的断言:A 调用了 B。这句话真假只能从代码、配置、部署清单里查。让模型凭印象补出来的边,看起来最合理的那几条往往最危险,因为它们符合通用范式,所以没人会去质疑。

验收动作:图生成完,拿出所有节点名做一次存在性核对,再抽查三到五条关键边回代码里找调用点。这两步花不了十分钟,但它是这张图从”示意”变成”依据”的分界线。

# 粗提图源里的节点标识(以 Mermaid 为例),逐个回仓库数一下有多少文件提到它
grep -oE '^[[:space:]]*[A-Za-z][A-Za-z0-9_]*' docs/arch.mmd \
  | sed 's/^[[:space:]]*//' | sort -u > /tmp/nodes.txt
while read -r n; do
  printf '%s: %s\n' "$n" "$(git grep -l -- "$n" | wc -l)"
done < /tmp/nodes.txt

这个正则只做粗提取,会把 graphsubgraph 这类图语言关键字一起捞出来,看结果时自己跳过即可;节点标识写在行首之外的位置也会漏掉,所以它是筛查工具,不是判定工具。文件数为 0 的节点,要么是你自己起的抽象名(那就写进图例说明),要么就是模型编的。想更严一点,把节点标识和显示文字分开核:标识回代码里搜,显示文字回文档和部署清单里搜,两边都落空的才判定为编造。

四、把图钉进仓库:渲染、diff 与协作层的坑

图源进版本库之后,才开始遇到真正跟工程有关的问题。

渲染在哪一层做,决定了后面有多累。 嵌在 Markdown 里靠平台渲染最省事,但各平台支持的语法子集不同,换平台可能就不显示;本地生成图片提交进仓库显示稳定,但每次改图都产生二进制 diff;构建时渲染最干净,代价是要维护渲染环境。

我倾向第三种,前提是把渲染命令固化下来,别让每个人手上的版本不一样:

# Graphviz
dot -Tsvg docs/arch.dot -o build/arch.svg

# PlantUML(需要 Java 运行环境)
plantuml -tsvg docs/arch.puml

# Mermaid 命令行
mmdc -i docs/arch.mmd -o build/arch.svg

二进制图片进仓库会持续报复你。 PNG 的 diff 是不可读的,两个人同时改图必然冲突,而且冲突后没法手工合并,只能一方重画。这是把图源文本化的核心动因——文本冲突至少能看懂冲突标记两侧各自改了什么,人工合并是可行的。如果你已经遇到了图源的合并冲突,处理思路和代码冲突一致,见 git 冲突让 AI 解

别指望模型自己去读大仓库。 让它”看看这个项目的架构画张图”,它读到的往往只是你打开的那几个文件加上目录名,剩下的靠推。大仓库的上下文获取本身就是个独立问题,见 大仓库上下文不足。稳妥的做法是你先把范围收窄到一个模块,给它明确的文件清单,一次只画一层。

关于工具选择:部分海外在线图表服务与托管型 AI 绘图产品,对中国大陆的可用性、账号注册与支付方式存在限制,具体以各家官方说明为准;本文只讨论走官方渠道能正常使用的用法,不涉及绕开区域限制的任何做法。落到工程上,长期维护的图建议用本地开源渲染器:图源、渲染器版本、字体都在你自己手里,不会因为某个在线服务改了策略或停服,就让整套文档一夜之间打不开。

五、什么情况下别再折腾

这一节比前面几节都重要。文本生成图有明确的能力边界,撞上了就该换路,硬磨只会耗掉一下午。

止损点一:同一张图来回改超过三轮还不对,停。 三轮之后还在错,说明问题不在图源,在你的描述本身有歧义,或者你自己对这块系统的理解就是模糊的。这时候正确动作是回去读代码,而不是继续换措辞。改措辞是在赌,读代码是在确认。

止损点二:布局怎么调都读不了,停止调布局,改拆图。 自动布局引擎的能力有上限,节点密到一定程度,任何参数都救不回来。拆成”总览图 + 若干局部图”,总览图只留主干,局部图各自展开一块。这是结构问题,不是渲染问题。

止损点三:这张图要的是设计感而不是准确性,换工具。 对外宣传材料、需要精确控制位置和留白的示意图,文本语法是错的选择——布局由算法决定,你控制不了。这类图用图形编辑器手工画反而快。

止损点四:图的生命周期不到一周,别进仓库。 没有维护意愿的图留在仓库里,半年后就是误导后人的错误资料。

回滚点:如果你把一张长期维护的图从图片改成了文本源,切换后一个月内出现两次以上”渲染环境出问题导致文档打不开”,回滚成图片是合理决策。文本化的收益是可维护性,如果稳定性的代价超过了它,这笔账不划算。

六、避坑清单

用中文或含空格的字符串当节点标识。 为什么会踩:写着顺手,模型也乐意配合。踩了会怎样:多数图语言的标识符不接受空格和部分标点,渲染直接失败,报错信息还常常指向下一行,让你查错地方。怎么避:标识符一律英文小写加下划线,显示文字放进方括号或引号里,两者分开。

让模型一次画完整个系统。 为什么会踩:省事,而且它真的会给你一张看起来很完整的图。踩了会怎样:节点数一多,编造的比例就上升,而且你没法逐条核实。怎么避:一次画一层,每层节点控制在十个以内,画完核实再画下一层。

图和代码分家。 为什么会踩:图放在文档系统里,代码在仓库里,各改各的。踩了会怎样:代码改了没人想起改图,三个月后图变成考古材料。怎么避:图源和代码放同一个仓库、同一个 pull request 里改,把”改了服务间调用关系必须同步改图”写进评审清单。

把生成的图直接当评审依据。 为什么会踩:图排版工整,看起来就很权威。踩了会怎样:一条编造的依赖边,可能让整场架构评审的结论偏掉。怎么避:图上标注生成日期和核对状态,未经核对的图明确标”草稿,未核对”。

图例缺失。 为什么会踩:画的人心里清楚实线虚线各是什么意思。踩了会怎样:换个人看,同一张图能读出三种意思。怎么避:只要图里出现两种以上线型或颜色,就必须有图例,这一条没有例外。

指望模型输出的图源格式每次一致。 为什么会踩:第一次给的格式很规整,就默认它每次都这样。踩了会怎样:脚本化处理时格式一变就断。怎么避:加一层格式校验,或者干脆先渲染再判断成功与否;结构化输出不稳定本身是个通用问题,见 结构化输出不稳

提交前自检

这张图提交之前,过一遍下面六条:

  1. 图上每个节点名,我能在仓库里指出它对应哪个目录或哪个服务;
  2. 关键路径上的每条边,我能说出它对应哪一次调用或哪条消息;
  3. 一个方框代表什么,全图口径一致,没有混用粒度;
  4. 出现两种以上线型或颜色的,图例齐全;
  5. 图源和相关代码在同一个提交里,渲染能在干净环境跑通;
  6. 图上有生成日期,未核对的部分明确标注了状态。

六条全过,这张图才配当依据用。过不了的,标成草稿也行,别让它悄悄流进决策链路。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。