组件与结构¶
A2UI 使用 邻接表模型 来表示组件层次结构。组件不是嵌套的 JSON 树,而是带有 ID 引用的扁平列表。
为什么使用扁平列表?¶
传统嵌套方法: - LLM 必须一次性生成完美的嵌套结构 - 难以更新深层嵌套的组件 - 难以增量流式传输
A2UI 邻接表: - ✅ 扁平结构,易于 LLM 生成 - ✅ 增量发送组件 - ✅ 通过 ID 更新任何组件 - ✅ 清晰分离结构和数据
邻接表模型¶
{
"surfaceUpdate": {
"components": [
{"id": "root", "component": {"Column": {"children": {"explicitList": ["greeting", "buttons"]}}}},
{"id": "greeting", "component": {"Text": {"text": {"literalString": "Hello"}}}},
{"id": "buttons", "component": {"Row": {"children": {"explicitList": ["cancel-btn", "ok-btn"]}}}},
{"id": "cancel-btn", "component": {"Button": {"child": "cancel-text", "action": {"name": "cancel"}}}},
{"id": "cancel-text", "component": {"Text": {"text": {"literalString": "Cancel"}}}},
{"id": "ok-btn", "component": {"Button": {"child": "ok-text", "action": {"name": "ok"}}}},
{"id": "ok-text", "component": {"Text": {"text": {"literalString": "OK"}}}}
]
}
}
组件通过 ID 而非嵌套来引用子组件。
组件基础¶
每个组件都有:
- ID:唯一标识符 (
"welcome-message") - 类型:组件类型 (
Text,Button,Card) - 属性:特定于该类型的配置
标准目录¶
A2UI 定义了按用途组织的标准组件目录:
- 布局:Row, Column, List - 排列其他组件
- 展示:Text, Image, Icon, Video, Divider - 显示信息
- 交互:Button, TextField, CheckBox, DateTimeInput, Slider - 用户输入
- 容器:Card, Tabs, Modal - 分组和组织内容
有关带有示例的完整组件库,请参阅 组件参考。
静态与动态子组件¶
静态 (explicitList) - 子组件 ID 的固定列表:
动态 (template) - 从数据数组生成子组件:
对于 /items 中的每一项,渲染 item-template。有关详细信息,请参阅 数据绑定。
注入值¶
组件通过两种方式获取值:
字面量 - 固定值:{"text": {"literalString": "Welcome"}}
数据绑定 - 来自数据模型:{"text": {"path": "/user/name"}}
LLM 可以生成带有字面量值的组件,或将它们绑定到数据路径以获取动态内容。
组合表面¶
组件组合成 表面(小部件):
- LLM 通过
surfaceUpdate生成组件定义 - LLM 通过
dataModelUpdate填充数据 - LLM 通过
beginRendering信号渲染 - 客户端将所有组件渲染为原生小部件
表面是一个完整、连贯的 UI(表单、仪表板、聊天等)。
增量更新¶
添加 - 发送带有新组件 ID 的新 surfaceUpdate
更新 - 发送带有现有 ID 和新属性的 surfaceUpdate
移除 - 更新父组件的 children 列表以排除移除的 ID
扁平结构使得所有更新都是简单的基于 ID 的操作。
自定义组件¶
除了标准目录外,客户端还可以定义满足特定领域需求的自定义组件:
- 方式:在您的渲染器中注册自定义组件类型
- 内容:图表、地图、自定义可视化、专用小部件
- 安全:自定义组件仍然是客户端受信任目录的一部分
自定义组件由客户端渲染器向 LLM 通告。LLM 随后可以在标准目录之外使用它们。
有关实现细节,请参阅 自定义组件指南。
最佳实践¶
- 描述性 ID:使用
"user-profile-card"而非"c1" - 浅层级:避免深层嵌套
- 分离结构与内容:使用数据绑定,而非字面量
- 使用模板重用:一个模板,通过动态子组件生成多个实例