我有一个网络应用程序。用户可以向位于 www.backend.io 的后端发送请求,该后端由 Cloudflare 管理(backend.io 的所有 A 和 CNAME DNS 记录均设置为仅 DNS)。后端通过
OpenAI APIs的
completions.create
调用 stream: true
。
开发过程中在我的本地主机上进行的测试表明流式传输效果良好;响应逐渐出现在屏幕上。但生产环境测试表明,最终整个响应是一次性发送的。
我尝试在 www.backend.io 上暂停 Cloudflare,但流式传输仍然无法正常工作。我还尝试创建另一台托管较小临时后端的服务器(back.temp.tech)。当我不使用 Cloudflare 时,流媒体运行良好;当我暂停 Cloudflare 时,流媒体也运行良好。
因此,即使我暂停 Cloudflare,我也不知道哪个 Cloudflare 设置可能会阻止流媒体与我的 backend.io 配合使用。有人有见解吗?
这是reactjs中的前端代码:
import React, { useState } from "react";
import { v4 as uuidv4 } from "uuid"; // import the uuid function
export default function Page() {
const [userMessage, setUserMessage] = useState("");
const [response, setResponse] = useState("");
const [requestId, setRequestId] = useState(""); // State to keep track of the current requestId
const handleMessageChange = (e) => {
setUserMessage(e.target.value);
};
const handleButtonClick = async () => {
const newRequestId = uuidv4(); // Generate a new unique requestId
setRequestId(newRequestId); // Set the requestId in the state
const res = await fetch("https://www.backend.io/httpOnly/complete", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ requestId: newRequestId, userMessage }), // Send the new unique requestId with the request
});
if (res.body) {
const reader = res.body.getReader();
let text = "";
return reader.read().then(function processText({ done, value }) {
if (done) {
setResponse(text);
setRequestId(""); // Clear the requestId after completing the request
return;
}
const v = new TextDecoder("utf-8").decode(value);
console.log(v)
text = text + v;
setResponse(text);
return reader.read().then(processText);
});
}
};
return (
<div className="App">
<input type="text" value={userMessage} onChange={handleMessageChange} />
<button onClick={handleButtonClick}>Send</button>
<div style={{ whiteSpace: "pre-wrap", textAlign: "left" }}>{response}</div>
</div>
);
}
这是后端代码:
const controllers = {};
app.post('/complete', async (req, res) => {
const requestId = req.body.requestId; // You need to send a unique identifier with each request
const controller = new AbortController();
controllers[requestId] = controller;
const userMessage = req.body.userMessage;
const stream = await openai.chat.completions.create({
model: 'gpt-4-1106-preview',
messages: [{ role: 'user', content: userMessage }],
stream: true,
}, { signal: controllers[requestId].signal });
for await (const part of stream) {
console.log("part", part);
console.log("part.choices[0]?.delta?.content", part.choices[0]?.delta?.content)
res.write(part.choices[0]?.delta?.content || '');
}
console.log("stream", stream)
res.end();
});
您可以尝试配置 Cloudflare 以绕过流端点的缓存和优化:
// Cloudflare Page Rule configuration
const pageRule = {
target: "www.backend.io/httpOnly/complete",
actions: {
disablePerformance: true,
bypassCache: true
}
};
如果这不起作用,您的应用程序可能会受益于手动刷新响应缓冲区以确保数据实时发送。您可以在每次 res.write() 调用后在后端代码中使用 res.flush() :
for await (const part of stream) {
res.write(part.choices[0]?.delta?.content || '');
res.flush();
}
让我知道效果如何。