AI 聊天 UI 最佳实践:设计更好的 LLM 界面
Source: Dev.to

大多数 AI 聊天界面都采用大致相同的骨架:底部是文本输入框,上方是一串气泡消息,之间还有一个加载指示器。这种布局对第一波 ChatGPT 包装器来说已经足够,但对于需要建立信任、留住用户并促成企业交易的产品来说,这远远不够。
“聊天演示”与“生产级 AI 聊天 UI”之间的差距比大多数团队预想的要大。它涉及流式传输的边缘情况、引用渲染、反馈收集、安全信号、会话持久化以及可访问性——这些都不是基础消息列表能免费提供的。
本文将介绍将精致的 AI 聊天 UI 与一次性原型区分开的设计模式。
为什么你需要的不止一个文本框
一个简陋的聊天界面会产生三个问题:
-
用户不知道该输入什么。
一个空的提示框里写着“随便问点什么…”,会让大多数人不知所措。他们需要指引、示例和约束。 -
用户无法了解当前状态。
模型在思考吗?请求失败了吗?仍在流式输出吗?没有明确的状态提示,用户往往会猜测最坏的情况。 -
用户不信任输出结果。
没有办法验证来源、标记错误答案或了解置信度。界面看起来像一个黑箱,只会“说话”。
一个优秀的 AI 聊天 UI 能解决以上全部问题:它为交互设定框架,传达状态,并赋予用户对输出的控制权。
流式响应渲染
流式是默认行为。用户会实时看到 token 出现,而等到完整响应才显示会显得不自然。但流式本身也会带来一些问题。
处理部分 Token
LLM API 往往会输出不完整的 markdown、部分代码块或未完成的单词:
- 在渲染前缓冲不完整的 markdown。半开的粗体标签不应破坏布局。
- 延迟代码块渲染,直到收到闭合的 fence,或在代码块内部显示“流式”指示器。
- 避免布局抖动。 每个新 token 不应导致整个消息重新布局。
停止与重试控制
用户需要能够中断并恢复:
- 在流式过程中停止生成。这不仅是便利功能,还能节省 API 成本。停止按钮应在流式时显眼。
- 重试上一次响应。一键重新生成,无需重新输入。
- 编辑并重新提交。高级界面允许用户编辑之前的提示并分叉对话。
abortController.abort()}
onRetry={() => retryLastMessage()}
aria-live="polite"
/>
引用与来源归属
信任 AI 输出取决于用户能否验证模型所说的内容。在准确性至关重要的场景(法律、医疗、研究、客户支持、企业搜索),引用 UI 不是可选项。
行内引用
最有效的模式:编号的行内引用,链接到可展开的来源卡片。
- 上标数字 出现在响应文本中(例如 “Revenue grew by 12 % [1]”)。
- 可点击的参考 可展开包含标题、URL 和摘录的来源卡片。
- 视觉区分 模型生成的文本与引用材料(背景着色或左侧边框)。
来源质量指示器
- 每条引用旁显示域名或出版商名称。
- 新鲜度指示器(来源最近更新时间)。
- 如果模型提供相关性分数,则显示置信度标记。
如果你的 AI 产品做出用户会据此行动的声明,引用 UI 是最重要的信任机制。
反馈收集
每一次 AI 的回复都是等待被捕获的训练信号。大多数反馈 UI 要么过于侵入,要么过于模糊。
分层反馈设计
将反馈结构化为多个层级:
- 低摩擦的第一层: 对每个回复进行点赞/点踩。始终可见,零额外点击。
- 可选的第二层: 在点踩时展开类别,如 “不准确”、 “不相关”、 “不完整”、 “有害”。预设选项胜过开放式文本字段。
- 深度反馈(可选): 通过 “告诉我们更多” 提供文本框。大多数用户不会使用,但使用的用户提供的信号价值最高。
submitFeedback(message.id, 'positive')}
onThumbsDown={() => setShowFeedbackForm(true)}
/>
{showFeedbackForm && (
setShowFeedbackForm(false)}
onSubmit={handleDetailedFeedback}
categories={['Inaccurate', 'Not relevant', 'Incomplete', 'Harmful']}
/>
)}
禁止的做法
- 不要打断对话流程来收集反馈。 行内控件优于模态对话框。
- 不要让它感觉像是工作。 超过两次点击,大多数用户会跳过。
- 不要忽视已收集的反馈。 如果看不到明显改进,用户会停止提供反馈。
安全指示器和内容审核
AI 产品在处理用户提示时需要可见的安全机制——以建立信任并满足合规要求。
内容警告
当模型生成敏感内容时:
- 在用户阅读之前以视觉方式标记(使用可折叠的警告横幅并提供用户控制)。
- 解释标记原因。具体的类别要胜过笼统的“内容警告”。
- 允许用户继续或关闭。除非政策要求,否则不要完全阻止。
Prompt Rejection
当安全过滤器拒绝提示时:
-
清晰解释。
“此请求被标记为涉及 [category]。请重新表述。”
优于 “我无法帮助。” -
保留用户输入。
拒绝后不要清空提示字段。 -
提供替代方案。
“相反,你可以询问 …” 能让对话继续进行。
对话历史与会话管理
单轮聊天只是玩具。能够持久化并自我组织的多轮对话才是产品。
历史持久化
- 自动保存每条消息 在完成后。不要依赖手动保存。
- 会话列表 显示在侧边栏或历史页面——为每个会话显示标题、时间戳和预览。
- 跨会话搜索。 随着用户积累对话,这一点至关重要。
上下文窗口管理
- 不要悄悄丢弃旧消息。 如果需要截断,请告知用户:
“使用最近的 20 条消息作为上下文。”
- 允许用户置顶重要消息,使其在截断时仍保持在上下文中。
- 为长会话提供对话分支。
多会话界面
专业使用场景需要多个并发会话:
- 侧边栏列出活跃会话,按项目或日期分组。
- 快速切换且不丢失滚动位置或草稿。
- 为团队产品提供会话共享。
AI 聊天的可访问性
不是可有可无的功能。它是企业销售的交易阻断性需求,也是许多司法辖区的法律底线。
流式传输和屏幕阅读器
- 在响应容器上使用
aria-live="polite",以便在不中断的情况下宣布新内容。 - 将
aria-atomic="false",仅朗读新令牌,而不是整个响应。 - 防抖公告 在快速流式传输期间——每几秒批量更新一次。
键盘导航
每个交互都必须可通过键盘访问:
- Tab 顺序: 提示输入框 → 发送按钮 → 响应区域 → 反馈控件 → 下一条消息。
- Escape(Esc)键: 关闭模态框、引用面板、展开卡片。
- 方向键: 在消息和建议提示之间导航。
- Enter 键: 提交(使用 Shift + Enter 换行)。
焦点管理
- 新响应完成?不要抢走提示输入框的焦点;用户希望立即跟进。
- 模态框打开?将焦点限制在内部。模态框关闭?将焦点返回到触发元素。
- 出现错误?将焦点移动到错误信息。
颜色与对比度
- 不要仅依赖颜色来区分用户和助手的消息——添加标签、对齐方式或图标。
- 所有文本:4.5:1 对比度(WCAG AA)。
- 交互元素需要 可见的焦点指示。
检查清单
- 流式传输: 缓冲部分 token,停止/重试控制,避免布局抖动。
- 引用: 行内编号引用,可展开的来源,质量指示器。
- 反馈: 分层收集,行内放置,低摩擦。
- 安全: 内容警告,可操作的拒绝,AI 生成的标签。
- 会话: 自动保存,可搜索历史,上下文透明。
- 可访问性: 实时区域,键盘导航,焦点管理,对比度。
您可以从头构建每个功能,或使用处理关键部分的组件开始。
我一直在 thefrontkit 构建可访问的 AI 交互组件。AI UX Kit 提供 React/Next.js 组件,覆盖完整的聊天生命周期:带附件的提示输入、流式响应查看器、引用面板、反馈收集以及会话管理——全部符合 WCAG AA 可访问性标准。还有一个用于身份验证、仪表盘和设置基础设施的 SaaS Starter Kit。浏览所有模板.