流式输出:让AI响应更流畅
流式输出技术让用户能够实时看到AI的生成过程,大幅提升交互体验, 是现代AI应用的必备技术。
流式技术对比
| 技术 | 实时性 | 复杂度 | 浏览器支持 | 适用场景 |
|---|---|---|---|---|
| SSE | ⭐⭐⭐⭐ | 低 | 优秀 | 单向推送 |
| WebSocket | ⭐⭐⭐⭐⭐ | 中 | 良好 | 双向通信 |
| 长轮询 | ⭐⭐⭐ | 低 | 通用 | 兼容性好 |
SSE实现示例
服务端实现
// Node.js SSE服务端
app.get('/api/stream', async (req, res) => {
// 设置SSE头
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('Access-Control-Allow-Origin', '*');
// 创建流式响应
const stream = await openai.chat.completions.create({
model: 'gpt-4',
messages: req.query.messages,
stream: true
});
// 发送数据
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
res.write(`data: ${JSON.stringify({ content })}\n\n`);
}
}
// 发送完成信号
res.write('data: [DONE]\n\n');
res.end();
});客户端实现
// 浏览器端SSE接收
class StreamClient {
constructor(url) {
this.url = url;
this.eventSource = null;
}
start(onMessage, onError) {
this.eventSource = new EventSource(this.url);
this.eventSource.onmessage = (event) => {
if (event.data === '[DONE]') {
this.close();
return;
}
try {
const data = JSON.parse(event.data);
onMessage(data.content);
} catch (e) {
console.error('Parse error:', e);
}
};
this.eventSource.onerror = (error) => {
onError(error);
this.close();
};
}
close() {
if (this.eventSource) {
this.eventSource.close();
this.eventSource = null;
}
}
}
// 使用示例
const client = new StreamClient('/api/stream?prompt=Hello');
let fullText = '';
client.start(
(content) => {
fullText += content;
updateUI(fullText); // 实时更新界面
},
(error) => {
console.error('Stream error:', error);
}
);WebSocket实现
// WebSocket服务端
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
ws.on('message', async (message) => {
const data = JSON.parse(message);
// 创建流式响应
const stream = await openai.chat.completions.create({
model: 'gpt-4',
messages: data.messages,
stream: true
});
// 流式发送
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
ws.send(JSON.stringify({
type: 'content',
data: content
}));
}
}
// 发送完成信号
ws.send(JSON.stringify({ type: 'done' }));
});
});
// WebSocket客户端
class WSClient {
constructor(url) {
this.ws = new WebSocket(url);
this.setupHandlers();
}
setupHandlers() {
this.ws.onopen = () => {
console.log('Connected');
};
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
switch (message.type) {
case 'content':
this.onContent(message.data);
break;
case 'done':
this.onComplete();
break;
}
};
}
send(messages) {
this.ws.send(JSON.stringify({ messages }));
}
}流式处理最佳实践
性能优化
- • 使用缓冲区减少网络开销
- • 批量发送小数据块
- • 实现背压控制
- • 合理设置超时时间
错误处理
- • 自动重连机制
- • 断点续传支持
- • 优雅降级策略
- • 错误状态展示
用户体验优化
打字机效果
// 打字机效果实现
function typeWriter(element, text, speed = 50) {
let index = 0;
function type() {
if (index < text.length) {
element.textContent += text.charAt(index);
index++;
setTimeout(type, speed);
}
}
type();
}加载动画
显示脉冲光标、进度条或骨架屏