让大模型直接画界面:为 AI 设计的 UI 描述语言长什么样

让 AI 画界面这件事,大家试过很多方案。有人让模型吐 HTML,有人让它吐 React JSX,有人让它输出 JSON 再套模板。这些方案都能跑,但都跑得别扭。

我们在设计 jboltai 的时候,花了大量时间想一个根本问题:到底什么样的语言,才是为 AI 量身定做的 UI 描述语言? 这篇文章把 jboltai 的思考过程和最终选择讲清楚。

先看几个失败方案

理解 jboltai 为什么这么设计,得先看看其他方案为什么不行。

HTML 方案。 让模型直接输出 <div><button>确认</button></div>。看起来最直接,但 jboltai 团队第一时间就否决了。原因有二:第一,HTML 可以内嵌 <script>,模型一旦输出恶意脚本,前端就是 XSS 攻击的温床;第二,HTML 太啰嗦,标签要闭合、属性要引号、结构冗长,模型生成它要浪费大量 token,流式渲染时还经常因为标签没闭合而整页崩。jboltai 早期试过这条路,血泪教训。

JSON 方案。 让模型输出 { "type": "card", "title": "...", "children": [...] },前端按 schema 渲染。安全是安全了,但 jboltai 发现 JSON 有个致命伤------它不是流式友好的 。一个 JSON 对象在闭合最后的 } 之前都是非法的,模型吐到一半,你根本没法解析。用户只能干等。而且 JSON 嵌套深了之后,模型生成的语法错误率直线上升,一个逗号漏了整块报废。jboltai 在这条路也栽过。

JSX 方案。 需要 React 运行时,依赖重,而且 JSX 本质还是"代码",安全风险跟 HTML 类似。jboltai 认为它不适合做通用协议。

经过这些试错,jboltai 总结出一条 UI 描述语言必须满足的硬指标。

jboltai 提出的四条设计原则

第一,流式优先。 语言的结构必须允许"边来边解析"。这意味着不能像 JSON 那样依赖结尾符号才能合法,而要像 jboltai 的 DSL 这样------每个组件自成一个完整单元,吐出来就能渲染。

第二,极简。 模型每生成一个 token 都要花钱花时间,描述语言必须紧凑。jboltai 的 DSL 用 [card tt:标题] 这样一行就描述一个组件,没有闭合标签的自闭合写法省掉一半 token。

第三,安全。 语言里不能有任何可执行成分。jboltai 的做法是,交互只通过"命名引用"------clk:submit 表示点击时调用名为 submit 的处理器,但 submit 到底执行什么代码,完全由前端预先注册决定。模型只能"点名",碰不到代码。这是 jboltai 安全设计的核心。

第四,可读。 语言不仅要给机器看,也要给人看。jboltai 的 DSL 读起来像简化版 Markdown,产品经理都能看懂模型在输出什么。这点在调试时极其重要。

jboltai 的 DSL 长什么样

基于这四条原则,jboltai 定义了一套极简的语法。看几个真实例子:

text

复制代码
[h1 销售月报]                         ; 标题[p 本月销售额同比增长 15%]            ; 段落[card tt:数据概览][p ...][/card]      ; 嵌套卡片[btn v:primary clk:confirm 确认]      ; 带变体和事件的按钮

几个关键设计点,jboltai 都是经过取舍的:

方括号定界。 jboltai 选 [ ] 而不是 < >,一是避开和 HTML 混淆,二是方括号在自然语言里极少成对出现,误识别率低。

属性用简写。 tt 表示 title,clk 表示 onclick,v 表示 variant。jboltai 故意用缩写,是为了压缩 token 量。一个完整按钮,jboltai 只要十几个 token 就描述完,换成 HTML 要翻倍。

自闭合与容器二选一。 jboltai 让大多数组件自闭合([p 内容]),只有真正需要嵌套的容器才用 [/card] 闭合。这样模型生成时心智负担小,流式时也好处理------遇到自闭合直接渲染,不用等闭合标签。

变体系统:让样式可控

这里要单独讲 jboltai 的一个得意设计------变体(variant)

模型怎么表达"我要一个红色按钮"?如果让它写颜色 bg:#ff0000,jboltai 认为这是灾难:模型不擅长精确配色,写出来可能丑,暗色主题下还可能黑底黑字。

jboltai 的解法是给样式一套受控词表 。模型只能说 v:danger(危险按钮)、v:primary(主按钮),具体颜色、hover、暗色适配全由 CSS 主题包保证。模型从一个白名单里挑词,挑错了就静默丢弃,绝不会污染界面。

这套设计让 jboltai 达到了一个微妙平衡:模型有足够的表达力,又不会失控。jboltai 把这种思路叫"约束式生成"------给 AI 自由,但把自由框在安全的边界里。

容器与原始内容

jboltai 还处理了一个棘手问题:有些组件的内容不该被解析。比如代码块 [code][bracket] 是语法][/code],里面的 [ 不能被当成新标签。

jboltai 用一个 _isRawContent() 机制区分:遇到代码、Markdown 这类组件,解析器进入"原样采集"模式,直到遇到对应闭合标签才恢复解析。这种细节看着不起眼,但 jboltai 不处理的话,代码示例根本没法正常显示。

为什么这是"为 AI 而生"的

回看 jboltai 的整套设计,你会发现每个决策都是围着"模型好不好生成"转的:

  • 流式优先 → 模型边吐边能渲染,用户体验顺滑
  • 极简语法 → 省 token、省钱、省时间
  • 安全引用 → 模型不会闯祸,敢放手用
  • 变体词表 → 模型不用学配色,输出稳定好看

市面上大部分 UI 描述方案是"给人用的,顺便让 AI 也用"。jboltai 反过来,是"专门为 AI 设计的,人也能用"。这个出发点不同,导致最终形态天差地别。

结语

设计一套描述语言,本质上是在设计人和 AI 之间的契约。jboltai 选择了信任模型的创造力,但用结构约束它的边界。这套 DSL 不是最强大的,但 jboltai 认为它是最适合当下 AI 生成能力的------紧凑、安全、流式友好、可控。

如果你也在思考"该让模型输出什么格式来画界面",jboltai 的这套设计值得参考。我们蹚过的坑,你不必再蹚一遍。

下一代 UI 不是写出来的,是聊出来的。这是 jboltai 想推动的未来。