A2UI 新增紧凑格式,降低生成界面开销
A2UI Express 通过 SDK 将紧凑的类 Python 语法编译为标准 JSON,据称最多可将 token 用量降至约三分之一。更新还支持受控生成方案,无需修改前端渲染器或组件目录即可调整推理路径。
AI 深度解读
生成式 UI 慢,不一定只能靠换更快的模型。Google 这次给 A2UI 的方案是:把模型生成的格式与客户端接收的协议拆开,让模型少写结构字符;对于布局固定的页面,再让模型只做选择,由代码组装界面。
原文给出的上限是:A2UI Express 将延迟降低至约三分之一,决策模型方案最高可提速 80 倍。但这两组数字不能混着看。前者仍然生成完整组件树,后者把布局限制在预先定义的范围内。对程序员更有用的,是看懂这两条路线各自省掉了什么工作。
让模型少写 JSON,为什么能加快出屏
A2UI 是面向 Agent 的生成式 UI 协议。客户端先声明一份可信组件目录,Agent 从中选择组件、描述界面,客户端渲染器负责画出来。它生成的是受目录约束的界面描述。
早期方案让模型直接输出 A2UI JSON 传输消息,连嵌套结构和每个花括号都要生成。作者认为,复杂 JSON Schema 约束下的树形输出既慢,也容易出错。
这次调整把两件事拆开:模型使用适合推理的格式,SDK 再用确定性代码将结果编译成标准 A2UI 消息。组件目录与渲染器可以继续使用。
推理格式包含提示词和编译器,两者都从目录的 JSON Schema 生成。提示词教模型怎么写,编译器负责转换和校验;目录没有声明的组件或属性,格式也无法合法表达。
下面这段代码展示了如何为生成器选择 Express:
from a2ui.processor import A2uiGenerator, CatalogConfig
from a2ui.inference_formats import ExpressFormatFactory
catalog = CatalogConfig.from_path("catalog.json")
generator = A2uiGenerator(
[catalog],
examples=few_shot_examples, # 只需编写一次 A2UI JSON 示例
inference_format_factory=ExpressFormatFactory(),
)
processor = generator.create_processor(renderer_capabilities)
system_prompt = f"{instructions}\n\n{processor.prompt_snippet}"
parts = processor.parse_response(model_reply) # 文本部分与经过校验的 A2UI 消息
重点是 inference_format_factory=ExpressFormatFactory():替换的是模型输出格式,最终交给客户端的仍是 A2UI 消息。已有 few-shot 示例也继续用 A2UI JSON 编写。
Express 已进入 Python 的 a2ui-agent-sdk 0.9.0、TypeScript 的 @a2ui/agent,以及 Dart 的 a2ui_agent 0.0.1-wip004。原文末尾另列出 npm 包版本 0.0.1。TypeScript 的配置方式是把 new ExpressFormatFactory() 作为生成器第三个参数。
Express 省了 token,也改变了流式输出的取舍
Express 使用接近 Python 的逐行赋值语法,变量名就是组件 ID。下面是原文的通知授权卡片:
surface("gallery-notification-permission")
$/description="Get alerts for order status changes"
$/icon="check"
$/title="Enable notification"
root=Card(main_column)
main_column=Column([icon, title, description, actions], _, "center")
icon=Icon($/icon)
title=Text($/title)
description=Text($/description, "body")
actions=Row([yes_btn, no_btn], "center")
yes_btn_text=Text("Yes")
yes_btn=Button(yes_btn_text, _, Event("accept", {}))
no_btn_text=Text("No")
no_btn=Button(no_btn_text, _, Event("decline", {}))
要看懂 main_column=Column(...) 这一行:参数按目录 Schema 的属性声明顺序映射,_ 表示跳过一个位置。$/title 绑定数据模型,Event("accept", {}) 声明服务端动作。语法变短了,但阅读时需要知道目录约定。
作者比较了四种格式:2025 年 12 月推出的 Direct JSON、最终成为新默认格式的 Express、使用 Lisp 风格 S 表达式的 Atom,以及使用 HTML 自定义元素的 Elemental。他们在 gemini-3.5-flash 上运行相同的 51 项任务,并分别开启、关闭 thinking。
原文称,Express 生成同类 UI 所需的 token 最多可减少到 Direct JSON 的约三分之一,延迟最高可提速 3 倍;关闭 thinking 时表现仍然良好。不过,提供的正文没有列出各格式的完整成绩和错误率,无法据此判断优势是否覆盖所有页面。
还有一个直接影响体验的限制:Python、TypeScript SDK 都支持逐块处理 Direct JSON,Express 则要收到完整回复后再编译。
总生成时间更短,不等于首批界面一定出现得更早。
Python SDK 还支持宏。例如模型只写 OrderStatus("ord_42"),宏再查询订单、填入真实值。这适合系统已经持有的数据,能减少让模型重新生成业务字段的需要。
固定页面为什么可以绕过完整组件树生成
设置页、结账页、确认页通常有已知结构。此时让模型从头设计布局,可能做了多余的工作。
TypeSafe 的 Jev 是原文所称的 System One 决策模型。它接收状态和带类型的问题,返回结构化决策及校准概率,不生成文本或 JSON。问题类型包括判断陈述是否成立的 Noul、从选项中选择的 Choice,以及按量表评分的 Score。原文称,一次请求可以回答多个问题,耗时约 100 到 300 ms。
开源工具 Apparite(jev2ui)把它接到 A2UI:提前用 Markdown grammar 定义布局问题,Jev 负责选择,代码负责组装组件,gemini-3.5-flash-lite 只写文案。
例如,设置行可以归入 switch、value、nav、check、danger。播客设置中的 Skip forward 被选为 value,Auto-download 为 switch,Log out 为 danger,示例概率均为 p ≈ 1.00。
整个过程分三步:一次 Jev 请求回答约 30 个布局问题;代码约在 200 ms 时通过 createSurface、updateComponents 发出带文案占位符的组件树;小模型随后把文字流式写入 updateDataModel。依赖文字内容的选择,再由小规模 Jev 请求补充决定。
在一次包含 11 个提示词的运行中,组件树出现在屏幕上的时间为 92 到 298 ms,页面完成耗时为 0.8 到 1.7 s,每页文案生成 101 到 341 个 token。Apparite 的两条 Jev 流水线在这 11 个提示词上都生成了有效 A2UI,项目也明确称这只是小样本初步结果。
代价是表达范围。它的 grammar 覆盖九种页面原型、十二种区块,范围之外的界面更适合 Express。而且 A2UI Agent SDK 尚未内置决策模型推理格式,Apparite 是集成示例。
我的判断
我认可这次拆分:客户端协议需要稳定,模型输出格式则应该允许替换。将语法转换和校验交给代码,也比要求模型准确生成大量嵌套结构更容易控制。
但提速数字必须带着前提读。Express 的结果来自指定模型和 51 项任务;决策模型的页面实验只有 11 个提示词。开头的「最高 80 倍」没有在提供的正文中交代足够完整的对照条件,不能直接理解为一般团队的页面端到端耗时都会缩短 80 倍。
语法校验也有边界。A2UI 有效,只说明消息满足协议约束,不能证明控件选得对、布局合理,或业务动作符合预期。示例中的高概率同样不能替代业务验证。
固定页面还应与普通模板渲染比较。如果输入数据已经能确定页面结构,直接写组件通常更省事;当用户意图、内容分类存在不确定性时,决策模型才可能补上有价值的一步。原文没有给出这类替代方案的对照数据。
能拿来做什么
- 已经使用 A2UI 的前端或 Node 团队,可以通过
npm install @a2ui/agent接入 Express,分别测量首批可见界面、完整页面耗时与 token 用量,再决定是否替换 Direct JSON。 - Python Agent 可以用
pip install a2ui-agent-sdk安装 SDK,按原文建议先测试 thinking 关闭的配置;订单状态等已有数据则适合通过宏查询并填充。 - 布局范围明确、但需要理解输入才能选择控件的页面,可以参考 Apparite,先列出可选布局和问题,再评估决策模型是否比现有规则更有收益。
- 需要让支持 skills 的模型遵守组件目录时,可以使用
SkillGenerator(ExpressFormat([catalog])).generate_skillset(),再通过skills.export_to_directory("skills")导出a2ui-core和每份目录对应的 skill,让目录约束进入模型的工作上下文。