我们第一版产品上线时,生成一份演示文稿要30秒。用户点击按钮,盯着转圈动画,等幻灯片出现时,他们早就新开标签页查邮件去了。问题不在AI,在我们对"生成"这件事的理解还停留在2019年。
这篇文章讲我们怎么修好的。不是靠新框架或神级库,而是重新想明白:2026年做AI演示工具,"生成"到底意味着什么。
答案不是批处理,是流式界面(Streaming UI)。
批处理思维是怎么害死产品的
如果你用过AI演示工具,应该熟悉这个流程:输入主题→等待→收到完整JSON→渲染整份幻灯片。这套模式做CRUD应用时没问题,但LLM(大语言模型)是逐字吐token的,等完整响应再展示,就像YouTube缓冲完整个视频才允许播放。
我抓住技术负责人问:"为什么我们把AI响应当数据库查询处理?"
流式界面不只是文字实时出现。核心是渐进式披露——信息可用时立即呈现,且对用户当下就有用。对演示文稿来说,这意味着:先生成标题让用户确认方向,再逐页流出内容,边生成边渲染,而非最后一次性弹出10页。
2026年这个模式无处不在:ChatGPT、Claude、Cursor AI,甚至Google的新vibe coding工具。React的架构,尤其是服务端组件(Server Components),恰好完美适配。
三层渐进架构:数据怎么流起来
我们最终确定的流程分三层:服务端生成流→SSE传输→客户端渐进渲染。数据从服务端流向客户端,逐层递进,而非打包投递。
React服务端组件(RSC)让我们在服务端渲染组件,不把JavaScript发往客户端。这对AI生成内容至关重要——内容常包含Markdown、需要清理的HTML、甚至图表数据。与其把这些逻辑塞进客户端,不如服务端处理:
// app/generate/[id]/page.tsx
async function PresentationPage({ params }: { params: { id: string } }) {
// 这段在服务端运行
const stream = await generatePresentation(params.id);
return ;
}
关键洞察:数据获取贴近数据源,降低延迟。再也不用"mount时用useEffect取数据"的瀑布流了。
我们用SSE(服务端发送事件)把数据从AI管道推到客户端:
// lib/presentation-stream.ts
export async function* generatePresentation(prompt: string) {
const llmStream = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages: [{ role: "user", content: prompt }],
stream: true,
});
let currentSlide = "";
for await (const chunk of llmStream) {
// 逐块处理,实时推送给客户端
}
}
渐进渲染:让用户提前参与进来
客户端用Suspense边界包裹每个幻灯片组件。服务端流到达时,对应幻灯片从骨架屏渐变为完整内容。用户看到的不是30秒白屏,而是1秒内出现标题,3秒看到第一页,10秒拿到完整大纲。
有个细节我们踩过坑:早期版本每收到一个token就重渲染,结果CPU飙高、界面卡顿。后来改成50ms批处理窗口,平衡了实时感和性能。
另一个教训是错误处理。流式传输中,服务端可能在第8页崩溃。我们学会了"优雅降级"——已生成的页面保留,错误信息以 toast 形式出现,用户可以选择重试剩余部分而非全盘重来。
上线三个月后,数据很直白:平均生成时间从30秒降到4.2秒,用户完成率(点击生成到保存成品)从23%涨到67%。最意外的是,用户开始把"看AI写幻灯片"当成产品体验的一部分,有人在社媒发录屏,配文"看它比我想得快"。
这让我们重新理解"延迟"——有时候用户讨厌的不是慢,是不知道在发生什么。30秒转圈是黑箱,4秒渐进是共创。
现在我们在实验更激进的方案:让用户在生成过程中点击任意幻灯片实时编辑,AI会据此调整后续内容走向。如果这能跑通,"生成"和"编辑"的边界就彻底模糊了——你不再是在等AI做完,而是在和它一起想。
流式界面改的不只是技术架构,是用户和AI的协作关系。批处理时代,AI是后台黑箱;流式时代,AI成了同桌办公的人——你看得见它一笔一画写,随时插嘴改方向。
有个用户反馈我记到现在:"以前用AI工具像交作业,等老师批完;现在像开会,边说边改。"
热门跟贴