Skip to content
语言特性

生成式 UI

智能体直接在对话中渲染丰富的交互式组件——表格、图表、表单、差异对比——而不仅仅是文字。无需编写任何前端代码。

内置支持
11 个组件
自定义可扩展

超越纯文本

传统聊天机器人 UI 将一切内容都渲染为文本气泡。但智能体产生的是结构化数据——查询结果、验证报告、部署状态、对比差异。将这些内容全部渲染为 Markdown 是糟糕的体验。

Haira 的生成式 UI 允许工具以声明式方式控制其输出的呈现方式。数据库查询结果渲染为表格。验证结果渲染为状态卡片。部署流水线渲染为进度追踪器。所有内容都直接内嵌在对话中,无需编写任何前端代码。

工作原理

工具使用 ui 模块返回 UI 组件。运行时对每个结果做两件事:

面向用户
富交互组件
通过 ARP 协议流式传输到前端,渲染为可交互的表格、卡片、图表或表单。
面向智能体
文本摘要
向大语言模型发送一段紧凑的文本表示,使其能够对数据进行推理并决定下一步操作。

两条路径互不牺牲。用户看到精美的表格,智能体看到结构化数据。

示例 — 带 UI 输出的工具
haira
import "ui"

tool query_database(query: string) -> any {
    """Executes a SQL query and displays results."""
    rows, err = postgres.query(db, query)
    if err != nil {
        return ui.status_card("error", "Query Failed", conv.to_string(err))
    }
    return ui.table("Query Results", headers, rows)
}

只需一行代码即可为智能体启用 UI:

haira
agent DataExplorer {
    provider: OpenAI
    tools: [query_database, search_data]
    ui: ui
    memory: conversation(max_turns: 30)
}

11 个内置组件

status-card
成功、错误、警告结果卡片,支持可折叠区域
table
可搜索、可滚动的数据表格,支持标签页和固定表头
code-block
带语法高亮和复制按钮的代码块,支持多标签页
diff
带语法高亮的前后对比,支持左右并排展示
key-value
带样式化数值的属性列表,用于元数据展示
progress
多步骤流水线追踪器,每步显示独立状态
chart
折线图、柱状图、饼图、面积图和散点图数据可视化
form
交互式表单,支持文本框、下拉框、复选框和多行文本字段
confirm
用于危险操作的是/否确认对话框
choices
按钮或列表形式的选项选择器,供用户做出选择
product-cards
用于电商和商品目录展示的图片卡片网格
用法示例
haira
import "ui"

ui.status_card("success", "Deploy Complete", "All 3 services updated")
ui.table("Results", ["Name", "Email"], [["Alice", "a@co"], ["Bob", "b@co"]])
ui.key_value("Server Info", {"Region": "us-east-1", "Status": "healthy"})
ui.chart("bar", "Revenue", ["Q1", "Q2", "Q3", "Q4"], [dataset])
ui.confirm("Delete this record?", "Yes, delete", "Cancel")
ui.group(
    ui.status_card("success", "Query Complete", "42 rows"),
    ui.table("Results", headers, rows)
)

自动生成的 Web UI

每个 Haira 工作流都会自动获得一个 Web UI。定义工作流,Haira 自动生成表单:

haira
@webui(title: "File Summarizer", description: "Upload a file and get an AI summary")
@post("/summarize")
workflow Summarize(document: file, context: string) -> { summary: string } {
    content, err = io.read_file(document)
    if err != nil { return { summary: "Failed to read file." } }
    reply, err = Summarizer.ask("Summarize: ${content}")
    if err != nil { return { summary: "AI error." } }
    return { summary: reply }
}

@webui 装饰器设置标题和描述。file 类型参数渲染为文件上传输入框。流式工作流(-> stream)会获得完整的聊天界面。

流式聊天 UI

流式工作流获得最丰富的体验——实时 token 流输出、工具执行卡片以及内嵌 UI 组件:

haira
@webhook("/chat")
workflow Chat(message: string, session_id: string) -> stream {
    return Assistant.stream(message, session: session_id)
}

fn main() {
    http.Server([Chat]).listen(8080)
}

聊天 UI 通过 ARP 协议进行通信——通过 WebSocket 或 SSE 处理文本增量、工具生命周期事件以及富组件渲染。

自定义组件

针对特定领域的需求,只需将 TypeScript Web Components 放入 components/ 目录:

components/gantt-chart.ts
typescript
export class HairaGanttChart extends HTMLElement {
  connectedCallback() {
    this.attachShadow({ mode: "open" });
  }
  setProps(props) {
    // Render your custom UI
  }
}

export default {
  tag: "haira-gantt-chart",
  component: HairaGanttChart,
};

自定义组件通过 CSS 自定义属性继承 Haira 的主题,并可以分发 haira-action 事件,这些事件将转化为聊天消息。编译器在构建时自动发现、打包并嵌入这些组件。

处理流水线

1
工具
通过 ui.* 函数返回有类型的数据
2
运行时
通过 WebSocket 或 SSE 发出 ARP 消息
3
前端
在对话中内嵌渲染对应组件

无需独立的前端仓库。无需维护 API 客户端。无需安装组件库。一个 .haira 文件,一个二进制文件,完整 UI。

Released under the Apache-2.0 License.