以前点外卖,下单后盯着进度条转圈圈,30分钟后突然"您的餐已送达"——这是传统模式。
现在外卖App实时显示:商家接单→备菜中→烹饪中→骑手取餐→骑行中→即将送达——每一步你都看得见。这就是Streaming。
好处不只是不焦虑,还有即时反馈:如果你发现AI输出的第一句话就跑偏了,可以立刻打断,不用等它整篇废话写完。
等AI回复就像等外卖——流式输出让你看着它"做",不用等它"做完"
传统模式下,你问AI一个问题,它思考10秒,然后一次性把答案甩给你——这10秒你盯着屏幕发呆。Streaming Response打破了这个等待:AI一边思考一边输出,你看着文字像打字机一样逐字显现。
延迟感:等10秒才开始显示
无法干预:生成过程不可见
内存占用:完整响应后才处理
用户焦虑:怀疑是不是卡住了
即时反馈:100ms就开始显示
可打断:随时可以停止生成
内存友好:边生成边消费
体验流畅:看着AI"思考"
// 传统模式:请求 → 等待 → 完整响应
const response = await openai.chat.completions.create({
messages: [{role: "user", content: "写首诗"}]
});
// 用户等了5秒...
console.log(response.choices[0].message.content);
// 流式模式:请求 → 立即开始接收 → 逐块显示
const stream = await openai.chat.completions.create({
messages: [{role: "user", content: "写首诗"}],
stream: true // 开启流式
});
// 100ms后就开始输出
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content || "");
}
// 输出:春眠...不觉晓...处处闻...啼鸟...
# 服务端推送格式
data: {"content": "春眠", "done": false}
data: {"content": "不觉", "done": false}
data: {"content": "晓", "done": false}
data: {"content": "", "done": true}
# 客户端接收
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (!data.done) {
outputDiv.textContent += data.content;
}
};
// WebSocket更适合需要交互的场景
const ws = new WebSocket("wss://api.example.com/stream");
ws.onmessage = (event) => {
const chunk = JSON.parse(event.data);
appendToOutput(chunk.content);
};
// 用户可以随时打断
stopButton.onclick = () => {
ws.send(JSON.stringify({action: "stop"}));
};
# Agent配置中启用
response:
streaming: true
chunk_size: "auto" # auto | token | sentence
buffer_ms: 50 # 缓冲50ms后发送
# 客户端调用
const response = await agent.run(prompt, {
stream: true,
onChunk: (chunk) => { console.log(chunk); },
onComplete: (full) => { console.log("Done!"); }
});
# 工具执行过程的实时反馈
tools:
- name: search_web
stream_progress: true # 显示执行进度
progress_messages:
- "正在搜索..."
- "分析结果中..."
- "整理答案中..."
proxy_read_timeout 86400s; proxy_buffering off;
# 按Token切分(精确控制)
chunk_size: token
chunk_tokens: 5 # 每5个token发送一次
# 按句子切分(更自然)
chunk_size: sentence # 完整句子再发送
# 自动模式(平衡性能和体验)
chunk_size: auto # OpenClaw智能调整
// Markdown流式渲染
let fullContent = "";
function handleChunk(chunk) {
fullContent += chunk;
// 使用debounce减少渲染频率
clearTimeout(renderTimer);
renderTimer = setTimeout(() => {
outputDiv.innerHTML = marked.parse(fullContent);
}, 100);
}
// 用户主动中断
const controller = new AbortController();
const stream = agent.run(prompt, {
stream: true,
signal: controller.signal
});
// 用户点击"停止生成"
stopBtn.onclick = () => controller.abort();
// 已接收的内容仍然保留
// 不必浪费已经生成的部分
✅ Buffer策略:不要每个token都发送网络请求,设置合理buffer
✅ 渲染节流:前端用debounce控制渲染频率(50-100ms)
✅ 渐进渲染:先显示纯文本,再逐步渲染Markdown格式
✅ 错误恢复:网络断开时缓存已接收内容,重连后继续
✅ 超时处理:设置stream timeout,避免无限等待