实现大模型打字机效果:NixAPI 流式输出完整教程
详解如何使用 NixAPI 的 Streaming 流式输出 API,在 Python、Node.js 和浏览器前端实现实时逐字显示效果,附完整可运行代码。
NixAPI Team 2025年1月22日
约 10 分钟阅读
ChatGPT 那种逐字输出的”打字机效果”,技术上叫做流式输出(Streaming),使用的是 HTTP Server-Sent Events(SSE)协议。
本文带你从原理到实现,完整走一遍。
为什么要用流式输出?
普通 API 调用需要等模型生成完所有内容才返回,如果生成一篇 1000 字的文章,可能要等 10-20 秒白屏。
流式输出让模型生成一个 token 就推送一个,用户立刻看到内容开始出现,体验好很多。
普通模式:▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ → 全部显示
流式模式:逐字 → 逐字 → 逐字 → 实时显示
Python 流式调用
from openai import OpenAI
client = OpenAI(
api_key="你的 NixAPI Key",
base_url="https://api.nixapi.com/v1",
)
# stream=True 开启流式模式
stream = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "写一首关于秋天的短诗"}],
stream=True, # ← 关键参数
)
# 逐块打印
for chunk in stream:
delta = chunk.choices[0].delta
if delta.content:
print(delta.content, end="", flush=True)
print() # 换行
运行后你会看到内容一个字一个字地出现,flush=True 确保不被缓冲区延迟。
Node.js / TypeScript 流式调用
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: '你的 NixAPI Key',
baseURL: 'https://api.nixapi.com/v1',
});
async function streamChat() {
const stream = client.chat.completions.stream({
model: 'gpt-4o',
messages: [{ role: 'user', content: '解释一下什么是向量数据库' }],
});
// 方式一:async iterator
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content ?? '';
process.stdout.write(text);
}
// 获取最终完整结果
const finalCompletion = await stream.finalChatCompletion();
console.log('\n总 token 用量:', finalCompletion.usage?.total_tokens);
}
streamChat();
在浏览器前端显示(React 示例)
import { useState } from 'react';
export default function StreamingChat() {
const [output, setOutput] = useState('');
const [loading, setLoading] = useState(false);
async function handleAsk() {
setOutput('');
setLoading(true);
const response = await fetch('https://api.nixapi.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${import.meta.env.VITE_NIXAPI_KEY}`,
},
body: JSON.stringify({
model: 'gpt-4o',
messages: [{ role: 'user', content: '用简单的话解释量子纠缠' }],
stream: true,
}),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value).split('\n');
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
const data = line.slice(6);
if (data === '[DONE]') break;
try {
const json = JSON.parse(data);
const text = json.choices[0]?.delta?.content ?? '';
setOutput(prev => prev + text);
} catch {}
}
}
setLoading(false);
}
return (
<div>
<button onClick={handleAsk} disabled={loading}>
{loading ? '生成中...' : '开始提问'}
</button>
<p style={{ whiteSpace: 'pre-wrap' }}>{output}</p>
</div>
);
}
安全提醒:前端代码里的 API Key 会暴露给用户,生产环境请在后端做中转。
注意事项
- 超时设置:流式请求可能持续较长时间,建议把 HTTP 超时设置到 120s 以上
- 错误处理:网络中断时要捕获异常并提示用户重试
- Token 统计:流式模式下
usage字段在最后一个 chunk 才会出现
小结
| 普通模式 | 流式模式 | |
|---|---|---|
| 参数 | 默认 | stream: true |
| 响应格式 | 单个 JSON | SSE 数据流 |
| 用户体验 | 等待后全显 | 实时逐字显示 |
| 适合场景 | 批处理、后台任务 | 对话界面、内容生成 |
👉 立即注册 NixAPI 免费体验流式输出