大模型对话界面的流式输出
大模型对话界面的流式输出
对话界面的重点是流状态、取消请求和不可信内容的安全渲染。模型输出应被视为外部输入。
流式状态不要直接拼接到渲染逻辑
用独立状态保存当前消息、完成消息和错误状态。请求被取消或组件卸载时,及时中止读取。
读取流的示例
const reader = response.body?.getReader();
if (!reader) throw new Error('响应没有可读流');
const decoder = new TextDecoder();
let text = '';
for (;;) {
const { done, value } = await reader.read();
if (done) break;
text += decoder.decode(value, { stream: true });
setDraft(text);
}
Markdown 渲染应关闭或严格过滤原始 HTML;代码块、链接和附件也要有明确的安全策略。
验证建议
测试断网、取消、服务端错误、超长输出和含 HTML 的输出,确认界面不会卡住或执行不可信内容。
把 流式消息的中断与渲染安全 放回一次真实改动里
做前端方案时,我通常先找一个会被频繁改动的页面或组件,而不是先把目录结构整体翻新。把这次改动涉及的入口、数据来源、使用方和退出条件写在同一张小清单里。这样评审时讨论的是“这处改动会让谁多拿一份状态、谁需要升级、出了问题怎样关掉”,不会停留在组件名称或框架偏好上。
接口的形状也值得先定下来。props、事件、缓存键、路由参数和错误对象只要有一个靠猜,调用方很快就会各自补一层兼容代码。宁可在边界处返回明确的空态或错误态,也不要用一个看似方便的默认值把问题藏起来。页面上出现空白时,开发者能从状态、网络记录和日志里顺着同一条线查下去,用户看到的提示也应说明下一步能做什么。
复核时看可观察的行为
复核不需要堆很多指标。选几条能说明问题的记录即可:一次正常完成的操作、一次被取消或失败的操作,以及一次刷新页面后的结果。把浏览器版本、构建产物、输入条件和观察到的现象留下来。若改动涉及缓存或异步请求,要刻意验证旧请求晚到时不会覆盖新结果;若涉及交互控件,则检查键盘操作和读屏文本没有随着视觉调整消失。
上线后也不要因为页面“看起来没问题”就把观察关掉。先约定一个短时间的观察范围,留意错误边界、资源加载失败和用户实际的退出位置。发现异常时,优先还原当时的输入与版本,再决定回滚还是补丁。这样的记录不华丽,却能让下一位接手的人知道这套 流式消息的中断与渲染安全 在什么条件下被验证过,哪些情况尚未覆盖。
不要把边角情况留给线上
关于流式对话的结论应当带着条件保存。它依赖的版本、输入形态和资源限制一变,过去的现象可能就不再成立。与其给出绝对判断,不如说明本次观察覆盖了哪些路径、刻意没有覆盖哪些路径。后续改动时先复用这些条件,再决定是否需要重新验证。
这类补充不会让方案显得更复杂,反而能避免讨论停留在抽象词上。真正要确认的是:输入变化后谁负责判断,结果写到哪里,失败会留下什么证据,以及操作人能否在不猜测的情况下恢复现场。
流式输出完成后再触发一次新的提问,确认旧 reader 已停止,新旧草稿不会交叉。错误提示应保留失败上下文,不能只显示“请求失败”。
消息展示的最后状态应和服务端完成状态对应;网络断开时也要让用户知道内容是否已经保存。
更多推荐



所有评论(0)