流式响应API
使用Server-Sent Events实现实时流式输出,让用户立即看到生成内容
SSE实时响应高级功能
什么是流式响应?
流式响应允许模型在生成内容时实时返回结果,而不是等待完整响应后再返回。 这极大提升了用户体验,特别是在生成长文本时。
❌ 传统方式
- • 等待完整响应(可能需要几秒)
- • 用户体验延迟
- • 超时风险
✅ 流式响应
- • 立即开始显示内容
- • 实时更新界面
- • 更好的用户体验
启用流式响应
在请求中设置 stream: true 即可启用流式响应。
请求示例
{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "user",
"content": "写一篇关于人工智能的文章"
}
],
"stream": true // 启用流式响应
}流式响应格式
流式响应使用Server-Sent Events (SSE)格式,每个数据块都以 data: 开头。
SSE数据格式
data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gpt-3.5-turbo","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gpt-3.5-turbo","choices":[{"index":0,"delta":{"content":"人工"},"finish_reason":null}]}
data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"gpt-3.5-turbo","choices":[{"index":0,"delta":{"content":"智能"},"finish_reason":null}]}
data: [DONE]重要字段说明
- •
delta: 包含增量内容 - •
finish_reason: 完成原因(stop/length/function_call) - •
[DONE]: 表示流结束
实现示例
Python实现
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.n1n.ai/v1"
)
# 创建流式响应
stream = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "讲一个故事"}],
stream=True
)
# 处理流式响应
for chunk in stream:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="", flush=True)JavaScript实现
async function streamChat(message) {
const response = await fetch('https://api.n1n.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: message }],
stream: true
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') {
console.log('Stream finished');
return;
}
try {
const parsed = JSON.parse(data);
const content = parsed.choices[0].delta.content;
if (content) {
process.stdout.write(content);
}
} catch (e) {
console.error('Error parsing:', e);
}
}
}
}
}React组件示例
import { useState } from 'react';
function ChatComponent() {
const [messages, setMessages] = useState([]);
const [isStreaming, setIsStreaming] = useState(false);
async function sendMessage(content) {
setIsStreaming(true);
const newMessage = { role: 'assistant', content: '' };
setMessages(prev => [...prev, { role: 'user', content }, newMessage]);
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: content, stream: true })
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
// 解析并更新消息
setMessages(prev => {
const msgs = [...prev];
msgs[msgs.length - 1].content += chunk;
return msgs;
});
}
setIsStreaming(false);
}
return (
<div>
{messages.map((msg, i) => (
<div key={i} className={msg.role}>
{msg.content}
</div>
))}
{isStreaming && <div>AI正在思考...</div>}
</div>
);
}最佳实践
错误处理
try {
// 处理流
} catch (error) {
if (error.name === 'AbortError') {
console.log('Stream aborted');
} else {
console.error('Stream error:', error);
}
}取消流
const controller = new AbortController();
// 开始流
fetch(url, {
signal: controller.signal,
// ...其他选项
});
// 取消流
controller.abort();缓冲处理
对于高频更新,考虑使用缓冲区批量更新UI,避免性能问题。
注意事项
重要提醒
- • 流式响应不支持
n > 1参数 - • 某些代理或防火墙可能不支持SSE
- • 流式响应的Token计算在流结束时返回
- • 确保正确处理连接中断和重连