AI 聊天 UI 设计与组件选型
将 Chat UI 能力需求映射到自建、assistant-ui、Vercel AI SDK 等实现方案的设计与选型综合笔记;不作为 assistant-ui 或 Chat UI 的 canonical 身份节点。
#synthesis
#growing
#frontend
#ai
[!info] related notes
- 上位概念: Chat UI
- 流式工程: AI 对话与流式界面, 前端 SSE 消费
- UI 组件: shadcn/ui
- assistant-ui 资源: assistant-ui
- assistant-ui 架构: assistant-ui 架构概览 · Thread & Message · Composer · ActionBar & BranchPicker · Runtime
AI 聊天 UI 设计与组件选型
知识库职责边界
这是一篇 selection / synthesis 笔记,不是框架资源页。
- “AI 对话界面是什么、有哪些通用能力”由 Chat UI 定义。
- “流式事件如何进入状态机并恢复”由 AI 对话与流式界面 解释。
- “assistant-ui 是什么、官网和仓库在哪里”由 assistant-ui 保存。
- 本页只回答:在已经明确需求后,应该自建哪些部分、采用哪类组件/运行时,以及为什么。
这能避免把 assistant-ui、AI Chat UI 等身份型别名同时挂在多个节点上。
AI 聊天的特殊需求
普通聊天组件不满足 AI 场景:
| 需求 | 普通聊天 | AI 聊天 |
|---|---|---|
| Markdown 渲染 | 不需要 | 必须(列表、加粗、代码块) |
| 代码高亮 | 不需要 | 必须 |
| 工具调用展示 | 不需要 | 必须(显示 LLM 调用了什么工具) |
| 流式打字机 | 不需要 | 必须 |
| 引用来源 | 不需要 | RAG 场景需要 |
| 安全警告 | 不需要 | 医疗场景需要 |
选型
| 方案 | 特点 |
|---|---|
| @assistant-ui/react | 专注 AI 聊天,组件化 |
| Vercel AI SDK UI | useChat + 简单组件 |
| react-markdown + 自建 | 轻量,缺工具调用展示 |
| 全自建 | 完全可控,工作量大 |
流式打字机效果
SSE 推送的文本片段逐步拼接到消息中:
onText: (text) => setMessages(prev => {
const last = prev[prev.length - 1];
if (last?.role === 'assistant') {
return [...prev.slice(0, -1), { ...last, content: last.content + text }];
}
return [...prev, { role: 'assistant', content: text }];
})
工具调用展示
LLM 调用 function calling 时,UI 需要展示调用了什么工具、传了什么参数:
[调用工具: extract_symptom_info]
body_part: 肩部
symptom_type: 疼痛
设计要点
- Markdown 渲染是基础 — AI 回复几乎总是有格式
- 流式状态管理 — 消息内容在不断变化,要避免不必要的重渲染
- 多种事件类型分发到不同 UI 区域 — 不是所有 SSE 事件都进聊天框
- 引用来源独立展示 — 不要混在聊天消息里
- 安全警告醒目 — 红色/橙色背景,图标提示
学习检查
不看正文回答:
- 为什么“Chat UI 是什么”和“选择 assistant-ui 还是自建”应该分成两个知识层?
- 哪些需求属于通用 Chat UI 能力,哪些才构成组件库选型条件?
- 如果后端 transport 从 SSE 换成 WebSocket,哪些 UI 设计原则应该保持不变?
- assistant-ui 的 Runtime/Primitive 分层解决了什么问题,又有哪些场景不值得引入它?
- 给 BodySense 或 MemoFlow 设计聊天界面时,列出必须自建、可复用组件库、以及应由 transport/runtime 层承担的职责。