想让外行看懂「我的服务用了什么」,最快的方式是给一张架构图。但会画架构图的人不多:画图工具要拖框连线,AI 生图出来的又是插画,不是工程图。我做了一个网页来填这个空缺——粘贴一句大白话,下载一张带各产品官方 logo 的工程制图风架构图。
比如对着它说「我开了个网店,用扣子做客服机器人,聊天记录存飞书」,几秒后得到的就是下面这张:
扣子、豆包、飞书都被画成带官方 logo 的节点,实线是主链路、虚线是定时任务,箭头没有压到任何一个字。操作界面就是最普通的网页:
推理全部走火山方舟 Seed 2.1。整个工具自己的结构,用它自己画出来是这样的:
方舟只做「听懂」这一步:从一句话里抽出节点、分组和连线。剩下的一切——坐标计算、走线避让、图标装配、渲染查错——都是确定性代码。这个分工是全文的核心判断,后面展开。先报实测结果:20 句真实场景全部出图,19 张通过零压线自查,平均 10.6 秒一张,20 句合计按量计费等价成本约 3 分钱(订阅套餐内边际成本为零)。
一、为什么不让模型直接画
让大模型直接写整页带坐标的 HTML 是这类工具的常见做法,但坐标恰恰是模型最容易算错的部分——一个节点放偏二十像素,箭头就穿过文字,而工程图对「线不压字」几乎零容忍。常见的补救是让模型渲染完自己看图、发现压线再改,一个循环下来又慢又不可靠。
我把这一层整个拆掉:模型只输出一个 {nodes, groups, edges} 的 JSON 规格——有哪些节点、谁和谁同组、连线的方向和性质,坐标一个像素都不碰。JSON 经过严格校验,不合法就带着具体错误自动重试;节点图标只能从一张约五十个条目的词表里选,拿不准就返回空,渲染层画首字母占位块兜底,模型永远不会发明一个不存在的图标名把流水线搞崩。
**模型负责它擅长的内容推断,坐标全部交给代码计算。**这是我在「一句话出 HTML 回答」项目里验证过的分工,这次换到架构图场景再一次成立。
二、中文 logo 是海外图标库的盲区
这类工具取 logo 的惯例是 svgl、devicon、gilbarbara 三个开源图标库依次回退。我把火山系产品和中文常用品牌逐个查了一遍,这条路对中文场景整体失效:火山引擎、豆包、扣子、飞书、微信、抖音、小红书全部没有收录——svgl 认识 TikTok,却不认识抖音。
| 品牌 | svgl | devicon |
|---|---|---|
| 火山引擎 / 方舟 / HiAgent / AgentKit | 无 | 无 |
| 豆包(含 Seed 系模型) | 无 | 无 |
| 扣子 / TRAE / 飞书 | 无 | 无 |
| 微信 / 抖音 / 小红书 | 无(有 TikTok) | 无 |
补救办法是自制一包本地图标源,在图标脚本里新增 volc/ 前缀(与 AWS、Google Cloud 官方图标源机制一致),配中英文别名表(方舟、公众号、扣子 直接命中)。九枚图标全部取自官方渠道,来路各不相同:
火山引擎和豆包用官网 favicon(192×192,磁贴显示只需 34px,余量充足);微信、抖音、扣子、小红书用 App Store 官方应用图标(512×512,走 iTunes 的 lookup 接口拿完整地址);飞书用官网 og:image 的尺寸模板改写成 512×512;定时任务没有品牌,用描线时钟。图标只用官方原版文件,不重着色、不裁切改形,图内声明指示性使用——与各家云厂商对自家架构图标的使用要求一致。
三、接方舟的两道坑
「听懂」这步调方舟的 OpenAI 兼容接口,撞到两个值得记下来的问题。
第一个是端点与 key 的对应关系。按量计费 key 打 /api/v3 返回 403 账户欠费,打订阅套餐端点 /api/plan/v3 返回 401 鉴权失败——两个方向各测了两把 key 才确认:订阅套餐端点只认套餐专用 API Key,按量 key 在那个端点上就是无效凭据。这个对应关系文档里不太显眼,谁先撞谁知道。
第二个是思考模式的代价。打通后第一轮探针,四句话的结构化抽取全部一次通过,但单次延迟 38 到 56 秒——回复 token 在 2600 到 3800 之间,而实际需要的 JSON 只有 300 到 500 token,大头全是模型默认开启的深度思考。这类「从一句话里抽节点连线」的任务不需要长推理,请求里显式关掉思考后,同一组任务延迟降到 4.1 到 6.4 秒,输出 token 缩减 85%,抽取质量没有变化:
| 对比项 | 开思考 | 关思考 |
|---|---|---|
| 单次延迟 | 38–56s | 4.1–6.4s |
| 输出 tokens/句 | 2679–3768 | 252–530 |
| 结构校验 | 4/4 通过 | 4/4 通过 |
四、排版引擎怎么防压线
常见做法是让 agent 读几何规则手册手排坐标、渲染完自己看图。我把它写成一个确定性排版引擎:按边的方向做最长路径分层,组内重心排序减少交叉,按工程制图的量化常量放节点,同组成员聚拢成连续块让分组框保持紧凑。边走线全部正交:同行水平、相邻行单弯、跨多行走「无碰撞走廊」——把每个中间行被节点占用的横向区间减掉,在剩余空隙里找一条贯穿通道,找不到就绕画布右侧;每条入边的末段竖线还要绕开分组框左上角的标签区。
写这个引擎的过程本身就是「坐标不能交给模型猜」的最好论据。调试期间有一版代码,行内布点循环的条件写成 if x > 0,而第一个节点放完后横坐标恰好还是 0,于是同一行所有节点全部叠在同一列——下游的走廊搜索、标签避让全在错误坐标上空转,报了十几种压线,根因就是这一行。这类 bug 模型手排坐标时天天都在犯,只是 agent 流程靠反复看图修图消化掉了;代码化之后它只出现一次,修掉就永久消失。
agent 流程里「渲染完自己看一眼 PNG」这步,我用 Playwright 写了检查脚本替代:在真实浏览器 DOM 上沿每条边逐点采样,断言没有任何线段穿过节点文字或标签文字,同时检查图标真实加载、无元素越界,浅色深色两个主题各查一遍。这个脚本在验证我手工排的第一张基准图时抓出过两处真压线——一个标签被左右两条竖线夹在 50 像素的缝里,缝的宽度装不下这个词。人眼很难发现这种 5 像素级的穿插,DOM 断言可以。
五、20 句实测:全部出图,19 张零压线
实测集覆盖公众号、小店客服、私活官网、课程制作、民宿管家五个非程序员视角的场景和十五个变体,含英文技术栈、九节点仓库工具链、三平台同时运营的长句,全部走真实链路(方舟 lite、关思考、订阅端点):
| 指标 | 结果 |
|---|---|
| 出图成功 | 20/20 |
| 确定性自查零违规 | 19/20 |
| 单句总耗时 | 平均 10.6s(图标缓存热身后约 7s;其中方舟抽取 3.2–5.1s) |
| tokens(20 句合计) | 输入 11914 / 输出 7964 |
| 按量计费等价成本 | 合计 ¥0.0310(订阅套餐内边际成本为零) |
二十句的题材跨度不小,六张实际输出先看一眼:
内容创作的完整流水线也排得开——脚本、配音、发布、评论回复各归其位:
开头那张网店客服图切到深色主题是这样:磁贴保持白底让 logo 不变色,只有纸面和线条换色:
初版引擎在两句复杂图上有压线:九节点十一边的仓库工具链有 10 处,AWS 英文栈的入边竖线穿过分组框角标。两类问题后来都修掉了——密集图靠组内聚拢加标签多轮避让,角标穿越靠末段竖线避让(入边落到组框内时,水平段自动下移到角标下方再入框)。修复后整轮重测全部通过。
剩下的唯一失败案例是一处边标签压线:长标签在三条线交汇处找不到净位。这是当前排版器的真实水平——五到八个节点的中小型技术栈最稳,标签在密集线网里的摆放仍有约二十分之一的失败率,且模型每轮抽取的连线略有随机,失败点随之漂移。如实交代。
六、克隆即跑
完整实现开源在 Vincent-chk/stack-diagram-ark(MIT,含排版引擎、网页版与图标包),排版与模板的基底是 MIT 协议的 caru-ini/stack-diagram,分叉说明见仓库 NOTICE:
git clone https://github.com/Vincent-chk/stack-diagram-ark
cd stack-diagram-ark/ark
cp .env.example .env # 填入方舟 ARK_API_KEY(订阅套餐 key 走 plan 端点)
bash start.sh # 浏览器打开 127.0.0.1:8000
依赖 Python 3.9+;PNG 渲染需要一次性安装无头 Chromium(pip install playwright && python3 -m playwright install chromium),不装也能拿到自包含 HTML。
边界与判断
当前的能力边界:节点数超过九个之后布局质量下降;密集线网里长边标签约二十分之一的压线概率;模型偶尔把托管平台既建成节点又建成分组(语义冗余但不致错);图标词表约五十个,词表外显示首字母占位块。
收拢到核心判断:把「听懂」交给 Seed 2.1,把「画准」交给代码。模型从一句话里抽出节点、分组和连线,承受全部的语言模糊性;坐标、走线、避让、自查全部由可测试的代码完成。非程序员得到的是打开网页就能用的工具,中文技术栈第一次在这类图里有了自己的官方 logo。