OpenAI API 依赖于 SSE(服务器端事件 https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format) 将响应流式传输回给您。如果您通过了stream当您的 API 请求中包含参数时,您将收到由 OpenAI 计算的数据块。
这会产生模仿某人打字的实时响应的错觉。
最难弄清楚的部分可能是如何将前端与后端连接起来。每次后端收到一个新块时,您都希望将其显示在前端中。
我创建了一个简单的 NextJs 项目Replit https://replit.com/@picsoung/OpenAi-Streaming这恰恰证明了这一点。现场演示 https://OpenAi-Streaming.picsoung.repl.co
你需要安装更好的 sse 包 https://www.npmjs.com/package/better-sse
npm install better-sse
服务器端在 API 路由文件中
import {createSession} from "better-sse";
const session = await createSession(req, res);
if (!session.isConnected) throw new Error('Not connected');
const { data } = await openai.createCompletion({
model: 'text-davinci-003',
n: 1,
max_tokens: 2048,
temperature: 0.3,
stream: true,
prompt: `CHANGE TO YOUR OWN PROMPTS`
}, {
timeout: 1000 * 60 * 2,
responseType: 'stream'
});
//what to do when receiving data from the API
data.on('data', text => {
const lines = text.toString().split('\n').filter(line => line.trim() !== '');
for (const line of lines) {
const message = line.replace(/^data: /, '');
if (message === '[DONE]') { //OpenAI sends [DONE] to say it's over
session.push('DONE', 'error');
return;
}
try {
const { choices } = JSON.parse(message);
session.push({text:choices[0].text});
} catch (err) {
console.log(err);
}
}
});
//connection is close
data.on('close', () => {
console.log("close")
res.end();
});
data.on('error', (err) => {
console.error(err);
});
现在您可以在前端调用此 API 路由
let [result, setResult] = useState("");
//create the sse connection
const sse = new EventSource(`/api/completion?prompt=${inputPrompt}`);
//listen to incoming messages
sse.addEventListener("message", ({ data }) => {
let msgObj = JSON.parse(data)
setResult((r) => r + msgObj.text)
});
希望这是有道理的,并帮助其他有类似问题的人。