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 消息的文本内容与 openuiLibrary 一起直接传递给 Renderer
在活动流期间传递 isStreaming={true},使 Renderer 在定义到达时优雅地处理未解析的引用。

openui-lang 格式

模型编写的是程序而非 JSON 规范。每条语句都是赋值;root 是入口点。官方提示词教会模型此格式,包括提升(hoisting)——先写 root 使 UI 外壳立即出现:
启用提升(推荐),root 行先写出,使页面结构立即出现,每个部分随着模型的定义逐步填充。

渐进式渲染工具

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

后续查询

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

最佳实践

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