Skip to main content
OpenUI 是一个生成式 UI 库,让语言模型以称为 openui-lang 的声明式格式生成完整的交互式 UI。智能体不是返回聊天消息,而是返回包含卡片、图表、表格、标签和表单的组件树,Renderer 将其转换为真实的 React UI。 这种集成非常适合数据丰富的输出,如报告、仪表板和数据浏览器,其中模型既是数据分析师又是 UI 设计师。

工作原理

  1. 生成系统提示词: 在启动时调用一次 openuiLibrary.prompt();它生成完整的 openui-lang 参考,模型用它来编写有效的组件树
  2. 在第一条消息时注入: 在新对话开始时将系统提示词作为开场系统消息发送
  3. 模型编写 openui-lang: 模型以程序形式(如 root = Stack([header, kpis, chart]))响应,而不是散文
  4. 使用 Renderer 渲染: 将文本传递给 OpenUI 的 Renderer 和组件库;它解析并渲染组件树

安装

OpenUI 需要 React 19+ 和 zustand。前端代码仅支持 React;LangGraph 智能体后端可以用 TypeScript 或 Python 编写。

导入组件样式

在你的 CSS 入口点或根组件中直接导入 OpenUI 的捆绑样式:

生成系统提示词

OpenUI 提供了 openuiLibrary.prompt() 函数,生成完整的 openui-lang 参考,包括所有组件签名、语法规则、流式处理提示和示例。在模块加载时调用一次:
preamble 覆盖默认角色。添加 additionalRules 来注入任务特定的约束:

通过 useStream 注入系统提示词

在每个新线程的第一条消息中发送系统提示词。检查 stream.messages.length === 0 以检测新线程并前置 system 消息:

使用 Renderer 渲染

将 AI 消息的文本内容直接传递给 Renderer 以及 openuiLibrary
在活跃流期间传递 isStreaming={true},以便 Renderer 在定义到达时优雅地处理未解析的引用。

openui-lang 格式

模型编写程序而不是 JSON 规范。每条语句是一个赋值;root 是入口点。官方提示词教模型这种格式,包括提升——先写 root 以便 UI 外壳立即出现:
启用提升(推荐),root 行先被写入,因此页面结构立即出现,每个部分在模型定义时逐步填入。

渐进式渲染工具

useStream 直接连接到 Renderer 会导致每个流式 Token 都重新渲染,产生数百次无效的重新解析。这会导致图表组件在数据尚未到达时崩溃。以下工具解决了这些问题: 将完整代码块复制到你的项目中,并将 stable 传递给 <Renderer>

后续查询

OpenUI 的 Button 组件支持 continue_conversation 操作类型。当用户点击后续按钮时,Renderer 触发 onAction,上面的 AIMessageView 将按钮标签作为下一条用户消息提交,与在输入框中输入的代码路径完全相同。 通过系统提示词中的 additionalRules 在每个报告末尾添加”深入探索”部分:

最佳实践

  • 在模块加载时生成系统提示词: 不要在 React 组件内;提示词有几 KB,应该只计算一次
  • 仅在新线程时注入系统提示词: 检查 stream.messages.length === 0,在后续轮次跳过注入,避免在线程历史中重复提示词
  • 使用提升顺序: 先写 root = Stack([...]);UI 外壳立即出现,各部分在模型定义时渐进式填入
  • 限制在完整语句上更新: 避免每个 Token 都重新渲染 Renderer;仅在完整语句(name = ComponentCall(...))到达时更新
  • 在渲染前验证图表数据: 图表组件需要其 Series 和标签数组在包含到稳定快照之前已定义
  • 保持 camelCase 变量名: openui-lang 解析器只接受 camelCase 标识符;在系统提示词的 additionalRules 中强化这一点