Beyond Text-Only AI: On-Demand UI Generation for Better Conversational Experiences

打开此文章的 LLM 可读版本

探索 AI 生成的用户界面如何通过在适当的时间动态创建正确的界面组件来增强人机交互,从而解决纯文本交互的关键限制。

Fatih Kadir Akın Fatih Kadir Akın

Beyond Text-Only AI: On-Demand UI Generation for Better Conversational Experiences

在当今 AI 驱动的世界中,我们越来越多地通过简单的文本界面与复杂的语言模型进行交互。虽然功能强大,但这种原始的文本通信模式引入了严重的用户体验挑战,限制了可访问性、效率,并最终影响用户满意度。

如果 AI 系统可以在需要时精确生成正确的界面组件,而无需开发人员预先构建每一种可能的 UI 变体,那会怎样?本文探讨了我关于一个新原型的工作,该原型使 LLM 能够按需创建动态的交互式 UI 组件,从而改变用户与 AI 系统和 MCP 服务器交互的方式。

纯文本交互的问题

与 AI 的基于文本的交互存在几个固有的局限性:

  1. 认知超载:用户必须将其结构化需求转化为非结构化文本
  2. 歧义性:自然语言本质上是模棱两可的,容易被误解
  3. 输入验证:没有用于确保正确数据格式或必填字段的保障措施
  4. 可访问性障碍:纯文本界面排除或复杂化了某些残疾人士的使用
  5. 效率瓶颈:键入复杂的指令既慢又容易出错
  6. 上下文管理:对于复杂的任务,文本线程很快变得难以管理
  7. 可视化限制:某些信息最好以视觉方式理解,而不是文本方式

对于企业应用程序、客户服务场景和复杂的工作流程,这些限制变得更加明显。考虑一下航运公司的客户支持系统——要求用户通过纯文本提供复杂的运输详细信息、跟踪号码或地址信息,这令人沮丧且效率低下。

AI 生成 UI 组件的承诺

解决方案在于使 AI 能够根据对话上下文动态生成适当的 UI 组件。当航运公司的客户需要更改其送货地址时,无需繁琐的文本交流:

Bot: 你的新地址是什么?
User: 主街123号
Bot: 哪个城市?
User: 纽约
Bot: 邮政编码是什么?
User: 10001
Bot: 哪个州?
User: NY

AI 可以生成一个完整的地址表单,该表单一次收集所有必需的字段,验证输入并提供适当的反馈——所有这些都保持了交互的对话性质。

这种方法弥合了对话式 AI 和传统应用程序界面之间的差距,为用户提供了两全其美的优势:对话的灵活性和自然性,以及结构化输入的精确性和效率。

LLM-UI 生成如何工作

从 LLM 生成 UI 的机制遵循以下通用模式:

  1. 请求解释:用户通过自然语言提出请求
  2. 意图识别:LLM 识别任务和所需的数据点
  3. 组件选择:LLM 确定适合该任务的 UI 组件
  4. 组件生成:LLM 生成定义 UI 组件的结构化 JSON
  5. 渲染:应用程序在对话响应旁边渲染组件
  6. 交互处理:用户与组件交互;数据被收集
  7. 结构化处理:收集到的结构化数据由 AI 或后端系统处理

从技术角度来看,LLM 生成一个 JSON 规范,描述所需的 UI 组件,客户端应用程序然后使用其组件库来渲染该组件。

与 MCP 集成

AI 生成的 UI 方法与 MCP 服务配合得非常好。正如我在之前关于 MCP 工具的文章中讨论的那样,MCP 提供了与 MCP 通信的标准化方法。通过扩展 MCP 服务器以接受来自 UI 组件的结构化数据,我们创建了一个强大的人机交互生态系统。

这种集成提供了几个好处:

  1. 标准化通信:UI 组件提供了一种一致的方式来收集和验证 MCP 服务的输入
  2. 降低认知负荷:用户与熟悉的界面模式交互,而不是学习特定于服务的文本命令
  3. 增强的功能:通过专门构建的界面,可以更轻松地访问复杂的 MCP 服务
  4. 数据验证:输入验证在数据到达 MCP 服务之前就在 UI 级别进行
  5. 无缝体验:用户不需要了解底层的 MCP 架构

例如,当用户想要访问文件系统 MCP 服务(如我在文件系统 MCP 服务器文章中所述)时,AI 可以生成一个直观的文件浏览器 UI 组件,其中包含熟悉的文件夹图标、面包屑导航和拖放功能,而不是看到原始的 MCP 输出 - 提供了一种自然的浏览和管理文件的方式,而无需文本命令。

AI 系统的 UI 组件类型

通过广泛的测试,我确定了几种组件类型,它们在 AI 生成的界面中提供了卓越的价值:

1. 表单 (Forms)

表单是结构化数据收集的主力军。它们可以同时收集多个相关的数据点,并进行适当的验证。表单非常适合:

示例表单 JSON 结构:

{"type":"form","data":{"id":"address-change","title":"Update Delivery Address","fields":[{"id":"street","label":"Street Address","type":"text","required":true},{"id":"city","label":"City","type":"text","required":true},{"id":"zip","label":"ZIP/Postal Code","type":"text","required":true,"validation":"^[0-9]{5}(-[0-9]{4})?$"},{"id":"country","label":"Country","type":"select","options":[{"label":"United States","value":"us"},{"label":"Canada","value":"ca"},{"label":"United Kingdom","value":"uk"}],"required":true}],"submitLabel":"Update Address"}}

2. 选择组件 (Selection Components)

决策界面帮助用户从定义的选项中做出选择:

示例按钮组件:

{"type":"buttons","data":[{"label":"Confirm","value":"confirm","variant":"primary"},{"label":"Reschedule","value":"reschedule","variant":"secondary"},{"label":"Cancel","value":"cancel","variant":"danger"}]}

3. 数据可视化组件 (Data Visualization Components)

用于清晰地呈现结构化信息:

示例表格组件:

{"type":"table","data":{"columns":["Shipping Option","Price","Estimated Delivery"],"rows":[{"Shipping Option":"Standard","Price":"$4.99","Estimated Delivery":"5-7 days"},{"Shipping Option":"Express","Price":"$12.99","Estimated Delivery":"2-3 days"},{"Shipping Option":"Next Day","Price":"$24.99","Estimated Delivery":"1 day"}],"caption":"Available shipping options for your order"}}

4. 复杂复合组件 (Complex Composite Components)

用于更复杂的交互:

真实示例:航运公司支持

为了展示这种方法的强大功能,我为航运公司的客户支持系统构建了一个原型。以下是原型中的一个简化对话:

用户:“我需要更改包裹的送货地址” AI:“我很乐意帮助您更新包裹的送货地址。首先,我需要您的跟踪号码。” [渲染带有跟踪号码字段的表单] 用户[提交带有跟踪号码“TRK12345678”的表单] AI:“谢谢!我找到了您到 [原始地址] 的包裹。它目前正在运输途中,预计明天送达。您想更改送货地址吗?” [渲染是/否按钮] 用户[点击“是”按钮] AI:“请提供您希望包裹运送到的新送货地址。” [渲染带有多个字段的地址表单] 用户[填写包含新地址信息的表单] AI:“感谢您提供新的地址详细信息。以下是更改的摘要:” [渲染比较新旧地址的表格] [渲染确认按钮] 用户[点击“确认”按钮] AI:“完美!我已更新包裹 TRK12345678 的送货地址。由于地址更改,送货日期已调整为 5 月 18 日。您将很快收到一封电子邮件确认。” [渲染显示更新后的交付时间表的进度指示器]

此交互演示了对话式 AI 与专门构建的 UI 组件的流畅集成。在每一步,都会根据当前上下文和用户需求生成适当的界面元素。

实施方法

AI 生成 UI 的实施需要几个关键组件:

1. 系统提示 (System Prompting)

LLM 需要有关可用组件以及何时使用它们的明确说明。以下是我的系统提示摘录:

您可以生成交互式 UI 组件作为响应的一部分。
当用户需要:
- 提供多条信息 → 生成表单 (FORM)
- 在选项之间做出选择 → 生成按钮 (BUTTONS)
- 查看结构化数据 → 生成表格 (TABLE) 或列表 (LIST)
- 查看实体详细信息 → 生成卡片 (CARD)

对于每种组件类型,请包含以下格式的 JSON:
\`\`\`ui-component
{
 "type": "componentType",
 "data": { /* component-specific properties */ }
}
\`\`\`

始终提供对话文本响应和适当的 UI 组件。
可以根据需要包含多个组件,每个组件都在自己的代码块中。
以下是您可以使用的组件:
...

2. 客户端渲染 (Client-Side Rendering)

客户端应用程序需要:

以下是一个 LLM 的原始响应在更改送货地址的情况下可能看起来的样子以及它将如何被解析的示例:

感谢您提供新的地址详细信息。以下是更改的摘要:
\`\`\`ui-component
{
 "type": "table",
 "data": {
  "columns": ["Detail", "Old Address", "New Address"],
  "rows": [
   {"Detail": "Street", "Old Address": "123 Main St", "New Address": "456 Oak Ave"},
   {"Detail": "City", "Old Address": "Los Angeles", "New Address": "San Francisco"},
   {"Detail": "Postal Code", "Old Address": "90001", "New Address": "94107"},
   {"Detail": "Country", "Old Address": "USA", "New Address": "USA"}
  ]
 }
}
\`\`\`
您确认吗?
\`\`\`ui-component
{
 "type": "buttons",
 "data": [
  {"label": "Confirm Changes", "value": "confirm_address_change", "variant": "primary"},
  {"label": "Edit Address", "value": "edit_address", "variant": "secondary"},
  {"label": "Cancel", "value": "cancel_changes", "variant": "danger"}
 ]
}
\`\`\`

在实践中,此响应可能会使用特殊标记嵌入在流式文本中。客户端代码将:

  1. 提取 UI 组件:解析 LLM 响应以识别任何 ui-component 规范
  2. 处理每个组件:验证和转换组件数据以进行渲染
  3. 渲染组件:使用适当的 React/Vue/etc. 组件来显示 UI
  4. 处理交互:为用户交互设置事件处理程序

以下是客户端处理的简化伪代码:

function processLLMResponse(rawResponse) {
 const response = convertRawResponseToJSON(rawResponse);
 // 提取文本内容
 const textContent = response.text;
 
 // 显示响应的文本部分
 displayMessage(textContent);
 
 // 处理每个 UI 组件
 if (response.components && response.components.length > 0) {
  response.components.forEach(component => {
   // 验证组件结构
   if (!validateComponent(component)) {
    console.error("Invalid component:", component);
    return;
   }
   
   // 根据类型渲染适当的组件
   switch (component.type) {
    case "table":
     renderTable(component.data);
     break;
    case "buttons":
     renderButtons(component.data, handleButtonClick);
     break;
    case "form":
     renderForm(component.data, handleFormSubmit);
     break;
    // 其他组件类型...
   }
  });
 }
}
function handleButtonClick(buttonValue) {
 // 将按钮值发送回 LLM
 sendToLLM({
  type: "ui_interaction",
  component: "button",
  value: buttonValue
 });
}

这种方法允许同步和流式响应,UI 组件与文本内容无缝地一起出现。

3. 设计系统 (Design System)

一致的设计系统确保组件:

挑战和未来方向

虽然充满希望,但 AI 生成的 UI 面临几个挑战:

技术挑战

  1. 延迟:生成 UI 规范会增加响应生成的时间
  2. 验证:确保生成的组件规范有效且安全
  3. 状态管理:在对话流程中维护组件状态
  4. 跨平台渲染:支持跨设备的一致体验
  5. 集成复杂性:确保跨平台(iOS、Android、web 等)的兼容性

UX 挑战

  1. 期望管理:设置关于 AI 功能的适当用户期望
  2. 交互设计:在文本和 UI 交互之间创建自然的过渡
  3. 可访问性:确保生成的 UI 对所有用户都可访问
  4. 一致性:在生成的组件之间保持视觉和行为一致性
  5. 可发现性:帮助用户了解可能进行哪些交互

未来研究方向

展望未来,进一步研究的几个有希望的领域包括:

  1. 自动化 UI 测试:可以测试生成界面的可用性和可访问性的系统
  2. 个性化界面:根据个人用户偏好和需求调整组件生成
  3. 多轮 UI 交互:在多个对话轮次中演变的组件
  4. 预测性 UI 生成:根据对话轨迹抢先生成界面
  5. 视觉-语言对齐:更好地集成视觉和文本元素
  6. 增强的 MCP 集成:跨 MCP 服务的 UI 组件生成的标准化协议

开始使用您自己的实现

对于有兴趣在自己的应用程序中实现 AI 生成的 UI 的开发人员,我建议从以下步骤开始:

  1. 定义您的组件库和规范
  2. 创建一个强大的系统提示,指示 LLM 何时以及如何生成组件
  3. 为每种组件类型实现客户端渲染
  4. 添加验证以确保组件满足结构和安全要求
  5. 从简单的组件(按钮、简单表单)开始,然后再转向更复杂的组件
  6. 与真实用户进行广泛的测试,以识别交互痛点
  7. 根据用户测试结果改进提示策略

结论

将 AI 生成的用户界面与对话系统集成代表了人机交互的重大飞跃。通过在正确的时间动态创建正确的界面组件,我们可以解决纯文本交互的固有局限性,同时保留对话的灵活性和自然性。

从我与 MCP 的合作以及此 UI 生成原型中,我发现最强大的 AI 体验并非来自纯文本或纯视觉界面,而是来自它们的周到组合。AI 交互的未来不在于在对话和传统 UI 之间进行选择,而在于让 AI 智能地为用户旅程中的每个时刻生成正确的界面。

本文已通过 AI 辅助进行校对和编辑。