AI 聊天 UI 设计
AI 聊天界面的核心需求:流式打字机效果、Markdown 渲染、工具调用展示、引用来源、安全警告。选型和实现方案。
#type / concept
#status / growing
#tech / dev / frontend
#tech / ai
[!info] related notes
- 前端 SSE: 前端 SSE 消费
- UI 组件: shadcn/ui
- assistant-ui 系列: 概览 · Thread & Message · Composer · ActionBar & BranchPicker · Runtime
AI 聊天 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 事件都进聊天框
- 引用来源独立展示 — 不要混在聊天消息里
- 安全警告醒目 — 红色/橙色背景,图标提示