设计稿转代码智能体。
一个能把设计稿变成"看起来一模一样"的标记语言的模型,解决的是容易的那一半,并给你造出了昂贵的那一半:截图没法说出"这是 Button 组件",于是一个像素级忠实的生成器会悄悄重造一个、把十六进制色值硬编码进去而不用 token,并且通过你所有的视觉复核。这样的东西发多了,设计系统就不再是一个系统。该拿来当交付目标的不是"截图对得上",而是产出里由既有组件构成的那个比例。
这份活儿是把东西翻译进一套词汇,而不是把像素誊写下来。
每一份设计都带着两层。一层是视觉结果,截图能完整捕获;另一层是产生这个结果的系统——供给颜色的那个 token、设计师拖进来的那个组件实例、从六级刻度里选出的那一档间距。被压平成图片之后,只有第一层活下来,而你的代码库跑的是第二层。
只拿到像素的智能体,做的更接近"针对布局的 OCR",而它那三种典型产出全都能通过视觉检查:
- 一个本来就存在、却被重造了一遍的组件。新的那个外观相同、行为全无:没有焦点环、没有禁用态、没有加载态、没有埋点、没有 story。它看起来是对的,直到有人改了真正的 Button,而十一个页面没跟着变。
- 该用 token 的地方写着字面量。
#d4421e而不是var(--accent),14px而不是那一档 16px。这在复核里看不见,对主题化却是致命的——本来一次变量替换就能搞定的暗色模式,变成了跨一百个文件的查找替换。 - 刻度之外、看着合理的数值。图片里没有任何东西说间距刻度只有六档,于是智能体量出 14 像素就写 14 像素。每一个脱离刻度的值都是一小笔永久的债,而且没有任何测试会标出它。
这些都不是模型能力问题,换个更强的模型也治不好。这是上下文问题:做出正确选择所需的信息,在智能体被问到之前就已经被销毁了。这就是上下文工程,也是这里的全部工作。
把清单交给它,否则它会自己发明一份。
智能体需要词汇,比需要图片更靠前。而把词汇凑齐,是针对多数代码库里本来就有的产物做的普通检索工作。
- token,连名带值。一份机器可读的清单——颜色、间距、圆角、字体——好让智能体把观察到的值映射到最近的合法值上,并且——这一点尤其关键——在压根没有合法值时能察觉。"这个颜色不在调色板里"是一条发现,不是一张自造色值的许可证。
- 组件的 API,不是组件的名单。只给名字,得到的是自信的误用。要给 props、变体、必需的子元素,以及一句"什么时候该选这个组件"。如果你的组件带类型,就从类型里抽出来,而不是维护一份会漂移的散文——工具 schema 与契约对工具的那套论证,对组件同样成立,因为对智能体来说,一个组件就是一件工具。
- 标准用法示例。每个常用组件配三到五个真实组合,胜过任何篇幅的描述——理由和"少样本示例胜过指令"在别处一样。
- 反面清单。被弃用的组件、那份谁都不该碰的遗留 CSS、只为一个老页面存在的那两个工具函数。智能体极擅长找到并模仿你最希望它去死的那段代码。
别把整套设计系统粘进提示词。一套成熟系统有几百个组件,而一个页面真正相关的大约十个;把这十个检索出来,与仓库导航是同一个问题,也有同一种失效模式——自信的错误定位比漏掉更贵,因为一个"差不多对"的组件真会被用上。
设计工具如今已经直接暴露了结构层。设计文件的节点树带着组件名与变体、颜色与间距的变量名,以及布局约束,而且可以通过一个 MCP 服务器读取,不必靠截图。真正承重的那一块,是"从设计组件到真实代码组件及其 import 路径"的显式映射——Figma 把它叫作 Code Connect,而值得知道的是:这份映射位于更高的套餐档位之后,因为它同时也是干活最多的那一部分。买不到的话,就自己把同一张表建起来:设计组件名 → import 路径 → props。它是一百行 YAML,并且胜过你会去尝试的任何提示词技巧。
如果你手上只有一张图,就把"抽结构"单列为一个被复核的步骤。
大量真实工作是以工单里的一张 PNG 的形式抵达的。直觉是把它丢给智能体、要一个组件;更好的形状是把结构抽取做成一个带人工闸门的独立环节——理由和"计划是比 diff 更便宜的闸门"一样。
- 第一趟:一棵布局树,不是代码。命名的区域、嵌套关系、重复("这是三张一模一样的卡片"),以及一份从每个区域到清单中某个组件的映射提案。它很小、两分钟就能读完,而且昂贵的错误恰恰在这里可见。
- 复核映射,而不是标记语言。一个设计师或工程师扫过"页头 → PageHeader,筛选行 → FilterBar,卡片 → ResultCard",会立刻抓住那个被发明出来的组件。同一个人去扫 300 行 JSX,不会。
- 第二趟:在已批准的映射约束下生成代码。映射一旦定死,生成就退化成填 props,而失效模式也缩到测试抓得住的范围。
- 把映射不上的记下来。任何智能体解析不到既有组件上的东西,要么是设计系统里一处真实的缺口,要么是设计师在系统外即兴发挥。两种都值得知道;两种都不该由"生成一个新组件"来悄悄了结。
视觉比对是错的裁判,而且它奖励的恰恰是错误行为。
截图比对是最显而易见的测试,可作为主要信号它比没用还糟——因为这篇手册讲的那种失败(一个看起来完美的一次性组件)拿到的正是满分。把视觉回归留着当"防止意外变更"的守卫,然后用另外三个数字来评判智能体。
- 复用率。渲染出的元素里,属于既有组件的占多少、属于新建组件的占多少?这个数字可以从 AST 里数出来,是唯一一个能预测"这个项目对你是帮忙还是帮倒忙"的指标,而且应当逐 PR 报出来。定一个下限,低于就判失败。
- token 遵循度。diff 里的颜色、间距、圆角与字体值,有多少能解析到 token 而不是字面量?一条 lint 规则通常就能白拿到大半,而且与复用率不同,它可以在提交时机械地强制。把它做成硬闸门——它是三者中最便宜的,也是保住主题化的那一个。
- 状态覆盖。设计画的是顺利路径。生产会给你空态、加载中、报错、只有一条、四百条、一个用不空格分词的语言写的名字,以及一个用 Tab 而不是鼠标的用户。智能体不会发明这些,因为图里没有,所以验收标准必须把它们逐条点名,而跑一趟测试生成是产出这些用例的合理办法。
在人去读之前,先用这三项给 PR 打分,正如补丁生成与测试驱动循环所主张的:应该由系统告诉智能体"你没过复用率下限,重来一次",而不是由复核者发现之后自己动手改。
无障碍与交互,字面意义上就不在那张图里。
一份设计稿里没有焦点顺序、没有角色、没有可访问名称、没有键盘行为、没有状态变化的播报,也没有动效。一个被要求复现外观的智能体,会产出一锅看起来没问题的 div 汤,而没有任何视觉测试会察觉。
- 让语义化组件成为唯一的路。这是第 2 步"清单优先"最有力的论据:如果智能体是用真实组件拼出来的,无障碍工作就是继承而来、而不是重新生成的。每一个手搓的元素,都是一处等着被用户发现的无障碍回归。
- 把自动检查放进循环里,做成硬闸门。axe 那一类规则能便宜且确定地抓出缺失的标签、对比度不足与没有标注的控件。把它们放进智能体的验证步骤,好让失败变成一次重试,而不是一条复核评论。
- 把交互规格作为一份独立输入来要求。什么可获得焦点、提交时会发生什么、列表更新时播报什么、Esc 键做什么。设计师或工程师各用一句话给出;智能体推断不出来,只会自信地猜。
- 机器查不了的那部分,留个人。自动化工具只能抓住真实无障碍缺陷中的一小部分。"视觉上没问题、语义上乱掉"的阅读顺序,是生成式标记语言最经典的失败,它需要一个带屏幕阅读器的人,而不是一条规则。
哪里划算,以及哪一种情况会让事情可量化地变糟。
这里的经济账异常清楚,因为决定两边的是同一个性质。
- 划算:用一套成熟系统拼装新页面。清单很大、设计师在系统内部作业、页面是已解决零件的重新组合。复用率天然就高,智能体干的是组合,省下的时间是真的。
- 划算:一份合规设计稿的前八成。结构、import、props 与布局,作为一个由人来收尾的起始 PR。按后台编码智能体的说法,把产出当成一份有具名主人的草稿——只有真有人合并它,吞吐增益才是真的。
- 划算:高频、低风险的界面。营销页、内部工具、后台管理页——那些"组件稍微不那么标准"的代价确实很低、而量又很大的地方。
- 不划算:没有系统的从零开始。没有东西可复用,于是每个页面都发明自己的词汇,一个季度下来你会有四十个近乎相同的按钮。这不是智能体造成的;它只是把人本来会干的事快四十倍地干了一遍。
- 不划算:定制视觉。一个全部价值就在于"看起来不像你的产品"的活动页,按定义复用率为零,而支配这篇手册的那个指标也就不再适用。
- 不划算:价值在交互上的任何东西。一个拖拽编辑器、一块画布、一份带条件逻辑的复杂表单。图里几乎不含规格,所以你做的不是设计转代码,是听写。
在为这一切下注之前,先跑一个十个页面的试点,并且只装一个仪表:渲染出的元素中属于既有组件的比例。如果复用率低于大约七成,你面对的就不是设计转代码的问题——你面对的是设计系统的问题,而智能体只会把这个缺口放大,不会把它补上。数字低时的正确反应,是停下页面生成,把这个季度花在清单上:token 列表、带类型的组件 API、设计组件到 import 路径的映射。这份活儿不好看,却是本页每一部分所依赖的东西,而且不管你最终有没有上智能体,它都是划算的。
相关:生成式 UI 模式讲的是相反的情形——智能体在运行时而非构建时拼出界面;代码评审智能体讲如何把复用率与 token 闸门做成评审而非 CI;而评估编码智能体讲如何建起那个告诉你"这一切到底有没有变好"的私有评测集。