当前位置: 首页 > news >正文

A2UI : 以动态 UI 代替 LLM 文本输出的方案

A2UI (Agent to UI) 是一个基于 JSON 的流式 UI 协议,旨在让 AI Agent 能够动态生成、控制并响应用户界面。从技术本质上看,它将 UI 视为纯粹的数据 payload,由前端运行时(Runtime)负责解析并映射为原生组件。
后端一直在生成固定格式的 json ,复杂的是前端runtime ,第一轮对话后 LLM call生成 JSON => UI ,UI 点击交互后又是新的 LLM call 之后生成的新 JSON => UI。
demo a2ui.org/quickstart/ 需要强网络环境。
初始交互流程与消息结构
在 A2UI 系统中,所有交互都始于标准的 JSON-RPC 消息。当用户在聊天框输入内容时,前端会封装一个message/send请求:

{ "jsonrpc": "2.0", "method": "message/send", "params": { "message": { "messageId": "28f374eb-5682-454a-9366-2350761362e4", "role": "user", "parts": [ { "kind": "text", "text": "查找纽约评分最高的5家中餐厅" } ] } }, "id": 1 }

后端 Agent 接收到此请求后,会调用大语言模型(LLM)。此时 LLM 的任务不仅是提供文本回复,还需要生成符合 A2UI 规范的 UI 描述 JSON。一个典型的 LLM 返回结构包含以下三个核心 DataPart:

[ { "beginRendering": { "surfaceId": "restaurant-surface", "root": "main-container" } }, { "surfaceUpdate": { "surfaceId": "restaurant-surface", "components": [ { "id": "main-container", "component": { "Column": { "children": { "explicitList": ["header-text", "result-list"] } } } }, { "id": "header-text", "component": { "Text": { "text": { "path": "title" }, "usageHint": "h1" } } }, { "id": "result-list", "component": { "List": { "children": { "template": { "componentId": "item-card", "dataBinding": "/restaurants" } } } } }, { "id": "item-card", "component": { "Card": { "child": "item-btn" } } }, { "id": "item-btn", "component": { "Button": { "child": "btn-label", "action": { "name": "view_detail", "context": [{ "key": "id", "value": { "path": "id" } }] } } } }, { "id": "btn-label", "component": { "Text": { "text": { "path": "name" } } } } ] } }, { "dataModelUpdate": { "surfaceId": "restaurant-surface", "path": "/", "contents": [ { "key": "title", "valueString": "推荐餐厅清单" }, { "key": "restaurants", "valueMap": [ { "key": "r1", "valueMap": [ { "key": "id", "valueString": "rest_001" }, { "key": "name", "valueString": "西安名吃" } ] } ] } ] } } ]

结论:A2UI 的核心逻辑是“UI 即数据”。Agent 通过surfaceUpdate定义组件的邻接表结构,通过dataModelUpdate注入业务数据。前端运行时负责维护这个状态并递归渲染。


用户交互触发的二次 LLM Call
当用户点击 UI 上的按钮(例如上述生成的“西安名吃”按钮)时,前端并不会执行本地的业务跳转,而是产生一个userAction回传给后端:

{ "userAction": { "name": "view_detail", "surfaceId": "restaurant-surface", "sourceComponentId": "item-btn", "timestamp": "2026-01-14T01:00:00Z", "context": { "id": "rest_001" } } }

后端 Agent 接收到此 Action 后,将其作为上下文再次请求 LLM,LLM 随后生成一段新的 UI JSON(例如该餐厅的详细预订表单)。
交互后 LLM 返回:动态生成的详情界面
后端 Agent 接收到userAction后,将其作为新的 Context 输入给 LLM。LLM 理解用户想要查看rest_001的详情,于是生成第二轮 UI JSON。这段 JSON 会覆盖或更新当前的渲染表面(Surface):

[ { "beginRendering": { "surfaceId": "restaurant-surface", "root": "detail-container" } }, { "surfaceUpdate": { "surfaceId": "restaurant-surface", "components": [ { "id": "detail-container", "component": { "Column": { "children": { "explicitList": ["detail-header", "booking-form"] } } } }, { "id": "detail-header", "component": { "Text": { "text": { "path": "restaurant_name" }, "usageHint": "h2" } } }, { "id": "booking-form", "component": { "Card": { "child": "form-fields" } } }, { "id": "form-fields", "component": { "Column": { "children": { "explicitList": ["phone-input", "date-picker", "confirm-btn"] } } } }, { "id": "phone-input", "component": { "TextField": { "label": { "literalString": "预订电话" }, "text": { "path": "/form/phone" } } } }, { "id": "date-picker", "component": { "DateTimeInput": { "label": { "literalString": "预订日期" }, "value": { "path": "/form/date" }, "enableDate": true } } }, { "id": "confirm-btn", "component": { "Button": { "child": "confirm-text", "primary": true, "action": { "name": "submit_booking", "context": [ { "key": "restaurantId", "value": { "literalString": "rest_001" } }, { "key": "phone", "value": { "path": "/form/phone" } } ] } } } }, { "id": "confirm-text", "component": { "Text": { "text": { "literalString": "确认预订" } } } } ] } }, { "dataModelUpdate": { "surfaceId": "restaurant-surface", "path": "/", "contents": [ { "key": "restaurant_name", "valueString": "西安名吃 - 第九大道店" }, { "key": "form", "valueMap": [] } ] } } ]

关键点:-上下文继承:LLM 记住了上一步选择的餐厅。

  • 动态组件切换:原本是列表页,现在变成了带有TextFieldDateTimeInput的预订表单。
  • 数据回传绑定confirm-btn按钮通过path绑定,会将用户在phone-input中输入的内容作为 Context 发回给后端。

标准组件库与渲染协议
A2UI 提供了一套标准组件库,目前包含 18 种原子组件,分为展示、布局、交互、表单四大类。
展示类组件 (Text, Image, Icon, Video, Audio)
这些组件负责内容呈现。以Image为例,其属性支持响应式填充:

{ "id": "poster", "component": { "Image": { "url": { "literalString": "https://cdn.example.com/img.png" }, "usageHint": "mediumFeature", "fit": "cover" } } }

布局类组件 (Row, Column, List, Card, Tabs, Divider, Modal)
布局组件通过children属性构建组件树。特别需要关注的是List组件的模板机制:
JSON

{ "List": { "direction": "vertical", "children": { "template": { "componentId": "reusable-card", "dataBinding": "/dataSourceArray" } } } }

运行时会遍历dataBinding指向的数据数组,为每个元素实例化一个componentId指定的模板组件。
交互与表单类组件 (Button, TextField, CheckBox, MultipleChoice, Slider, DateTimeInput)
TextField等组件支持数据双向绑定。当用户输入时,运行时会自动更新内部 DataModel:

{ "TextField": { "label": { "literalString": "联系电话" }, "text": { "path": "/form/phone" }, "textFieldType": "number" } }

数据绑定系统 (DynamicValue)
A2UI 弃用了硬编码字符串,所有属性均使用DynamicValue结构,支持literal(字面量)和path(路径绑定)两种模式:

类型数据模型示例JSON 绑定配置渲染结果
DynamicString{"name": "Alice"}{"path": "name"}"Alice"
DynamicNumber{"price": 99}{"path": "price"}99
DynamicBoolean{"valid": true}{"path": "valid"}true

数据路径支持绝对路径(以/开头)和相对路径(在模板循环中使用),这使得 UI 结构可以保持高度复用,仅通过切换数据源即可改变展示内容。
定制性边界
要理解 A2UI,必须明确 LLM 能做什么,以及它被禁止做什么。这类似于现代 Web 开发中的“设计系统”与“业务逻辑”的分离。
LLM 拥有完全控制权的部分(What & Where)
LLM 决定界面的业务逻辑和结构,这部分是完全动态的:

  1. 组件树拓扑:决定是先显示文字还是先显示图片,决定使用 Row 还是 Column 进行包装。
  2. 组件类型:根据上下文选择最合适的组件(如:发现需要用户输入时,动态生成TextField)。
  3. 数据映射:定义 UI 组件读取数据模型的哪个分支。
  4. 布局权重:通过weight属性(flex-grow 的 JSON 映射)决定组件占据的空间比例。
  5. 交互逻辑:定义按钮点击后发送给后端的 Action 名称和参数名。

前端 Runtime 强制控制的部分(How it looks)
为了防止 LLM 生成风格诡异、不可用或不安全的界面,样式权限被锁死在前端:

  1. 视觉样式 (CSS):LLM 无法指定具体的十六进制颜色(如 #FF0011)或像素值(如 14px)。所有的颜色、圆角、内边距、字体族都由前端的主题文件(Theme)预先定义。
  2. 交互细节:按钮点击时的缩放动画、列表滚动的物理惯性、输入框聚焦时的边框高亮。
  3. 响应式规则:在窄屏手机和宽屏显示器上如何折行,这由前端的 CSS Media Queries 固定处理。
  4. 底层实现Button在 HTML 中是用<button>还是<div>模拟,LLM 并不感知。
维度LLM 控制 (JSON 描述)前端控制 (Hardcoded/Theme)
内容✅ 文字内容、图片 URL、选项列表❌ 字体族、行高、字符间距
结构✅ 组件层级、排列顺序❌ 组件内部 DOM 嵌套
样式⚠️ 语义标记 (usageHint="h1")✅ 具体的 px、hex 颜色、阴影值
布局✅ 水平/垂直、flex 比例❌ 具体的 gap 间距、响应式断点
交互✅ 点击触发什么 Action✅ 点击时的视觉反馈、动画过渡

技术架构总结
A2UI 渲染器本质上是一个状态机。其核心逻辑如下:

// 渲染器核心伪代码逻辑 class A2uiRenderer { private surfaceState: Map<string, Surface>; processMessages(payload: JSON) { if (payload.surfaceUpdate) { // 1. 更新扁平化的组件注册表 this.updateComponents(payload.surfaceUpdate); } if (payload.dataModelUpdate) { // 2. 更新响应式数据源 this.updateDataModel(payload.dataModelUpdate); } // 3. 触发 UI 递归重绘 this.requestRender(); } renderNode(nodeId: string) { const config = this.getComponentConfig(nodeId); const componentClass = registry.get(config.type); // 自动解析数据绑定 const props = this.resolveProps(config.props, this.dataModel); return new componentClass(props, config.children); } }

总结:作为“协议”而非“框架”的 A2UI
从工程角度看,A2UI 类似于一种“强约束的低代码协议”。它的判断逻辑如下:

  1. 它是声明式的:后端不发送 JavaScript 代码,只发送 UI 的状态快照。
  2. 它是闭环的:前端的每一个有效操作(Action)都会导致后端生成新的 JSON 响应,从而驱动界面进入下一个状态。
  3. 它是安全的:由于 CSS 和底层 DOM 结构的解释权在前端,恶意 LLM 无法通过注入stylescript标签来进行 XSS 攻击或破坏 UI 规范。

这种设计的核心价值在于:它让 AI Agent 拥有了“长出手脚”的能力,能够直接通过界面引导用户完成复杂的业务流程,而不仅仅是作为一个聊天窗口存在。

http://www.jsqmd.com/news/245987/

相关文章:

  • DeepSeek-R1如何提升推理速度?CPU优化部署实战案例
  • CosyVoice-300M Lite技术揭秘:如何实现高效语音合成
  • 在线m3u8转MP4
  • UE5 C++(29-2):描述碰撞响应方式的枚举类 enum ECollisionResponse。
  • BGE-Reranker-v2-m3参数详解:FP16加速与显存优化技巧
  • bert-base-chinese教程:中文实体关系抽取详细步骤
  • JLink驱动开发核心要点:HID接口数据交互原理
  • Qwen3-VL-WEB快速体验:三步完成网页端AI推理任务
  • 轻松搞定中文ITN转换|科哥开发的FST镜像一键部署指南
  • 5分钟部署BGE-M3:一键启动文本检索服务,小白也能搞定
  • Qwen3-1.7B实战项目分享:构建个人AI助手
  • 没GPU如何微调VoxCPM?云端LoRA训练极简方案
  • DeepSeek-R1-Distill-Qwen-1.5B自动化测试:性能基准多次运行脚本实例
  • BGE-M3部署指南:多节点分布式方案
  • Proteus电路仿真实战案例:步进电机驱动仿真分析
  • ComfyUI参数详解:ControlNet精准控制图像生成全解析
  • 简单入门seleniumUI自动化测试
  • AI音乐创作新范式|NotaGen WebUI一键生成古典乐
  • TensorFlow-v2.15性能测评:不同GPU型号推理延迟对比
  • 5分钟上手Z-Image-Turbo,文生图AI开箱即用实战指南
  • 2026年开发者必备:IQuest-Coder-V1开源部署趋势分析
  • nrf52832的mdk下载程序新手教程:从零开始
  • Supertonic部署案例:智能音箱语音系统改造
  • 经典面试题:如何测微信的朋友圈?
  • 金融播报场景适配:IndexTTS2专业语调调节技巧
  • SGLang-v0.5.6环境配置:CUDA版本兼容性问题解决
  • Qwen2.5-0.5B人力资源:简历筛选对话机器人
  • 电商智能修图踩坑记录:用Qwen-Image-Edit-2511避开这些陷阱
  • 听完就想试!这段带情绪标签的语音识别太真实了
  • Z-Image-Turbo风格库建设:预设模板管理与复用机制