如何在Cloudflare部署的Svelte服务端流式返回OpenAI API响应?
问题
Svelte文档中给出了在+svelte.js文件中处理POST请求并返回普通响应的示例:
export async function POST({ request }) { const { a, b } = await request.json(); return json(a + b); }
但文档未提及如何流式返回响应。我需要在POST请求中调用OpenAI API获取流式响应,代码如下:
export async function POST ({ request }) { const completion = await openai.chat.completions.create({ messages: [{ role: "system", content: prompt }], model: "gpt-3.5-turbo", stream: true, }); for await (const chunk of completion) { console.log(chunk.choices[0].delta.content); } }
我需要将每个chunk.choices[0].delta.content逐段流式返回给发起请求的页面。此前用Express时可通过res.write(data)实现流式响应,但Express无法部署在Cloudflare上,因此需要找到适用于Svelte且兼容Cloudflare的等效方法。
解决方案
在SvelteKit(兼容Cloudflare Pages/Workers)中,要实现流式响应,需返回包含ReadableStream的Response对象,替代默认的json()辅助函数,具体实现如下:
基础流式响应实现
export async function POST({ request }) { // 解析请求中的参数 const { prompt } = await request.json(); const completion = await openai.chat.completions.create({ messages: [{ role: "system", content: prompt }], model: "gpt-3.5-turbo", stream: true, }); // 创建可读流处理分块数据 const stream = new ReadableStream({ async start(controller) { try { for await (const chunk of completion) { const content = chunk.choices[0]?.delta?.content; if (content) { // 将文本编码为Uint8Array写入流 controller.enqueue(new TextEncoder().encode(content)); } } } catch (error) { controller.error(error); } finally { controller.close(); } } }); // 返回带流式内容的响应 return new Response(stream, { headers: { 'Content-Type': 'text/plain; charset=utf-8', 'Transfer-Encoding': 'chunked' } }); }
Server-Sent Events(SSE)格式适配
如果前端需要用SSE接收响应,只需修改流的写入格式和响应头:
// 在流的start方法中修改写入内容 if (content) { controller.enqueue(new TextEncoder().encode(`data: ${content}\n\n`)); } // 修改响应头 return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' } });
前端接收示例
const response = await fetch('/api/your-endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: '你的提示内容' }) }); const reader = response.body.getReader(); const decoder = new TextDecoder(); const outputElement = document.getElementById('output'); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); outputElement.textContent += chunk; }
Cloudflare Workers/Pages原生支持ReadableStream,上述方案完全兼容Cloudflare部署环境。
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

