You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vercel Serverless函数中实现流式响应?本地正常部署失效

解决Vercel Serverless Functions部署后流式响应失效的问题

你的核心问题是Vercel Serverless Functions默认会缓冲所有响应内容,直到函数执行完毕才一次性返回,导致流式打字效果失效。以下是具体修复方案:

关键修复步骤

  • 设置Vercel专属头部禁用响应缓冲
  • 配置正确的响应内容类型与缓存控制
  • 修正流式写入逻辑,避免重复输出HTML结构

修改后的核心代码

const { Configuration, OpenAIApi } = require("openai");

const configuration = new Configuration({
    apiKey: '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',
    // 请替换为你自己的OpenAI API密钥
});
const openai = new OpenAIApi(configuration);

export default async function handler(req, res) {
    // 1. 禁用Vercel响应缓冲,开启流式传输
    res.setHeader('X-Vercel-Buffer-Response', 'false');
    // 2. 配置响应头:指定内容类型,禁用缓存
    res.setHeader('Content-Type', 'text/html; charset=utf-8');
    res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    res.setHeader('Pragma', 'no-cache');
    res.setHeader('Expires', '0');

    // 3. 先输出HTML基础结构,仅执行一次
    res.write("<!DOCTYPE html><html><body>");

    try {
        const completion = await openai.createChatCompletion({
            model: "gpt-3.5-turbo",
            stream: true,
            messages: [
                { role: "system", content: "You are an AI." },
                { role: "user", content: "how are you?" }
            ],
        }, { responseType: 'stream' });

        completion.data.on('data', data => {
            const lines = data.toString().split('\n').filter(line => line.trim() !== '');

            for (const line of lines) {
                const message = line.replace(/^data: /, '');
                if (message === '[DONE]') {
                    // 4. 流结束时关闭HTML标签并结束响应
                    res.write("</body></html>");
                    res.end();
                    return;
                }
                try {
                    const parsed = JSON.parse(message);
                    const content = parsed.choices[0].delta.content;
                    if (content) {
                        // 流式写入内容
                        res.write(content);
                    }
                } catch (error) {
                    console.error('解析流消息失败', message, error);
                }
            }
        });

        // 监听流错误事件,确保异常时正确结束响应
        completion.data.on('error', (err) => {
            console.error('OpenAI流请求错误', err);
            res.write('<p>请求发生错误,请重试</p></body></html>');
            res.end();
        });

    } catch (error) {
        console.error('OpenAI请求出错', error);
        res.write('<p>请求发生错误,请重试</p></body></html>');
        res.end();
    }
}

修复说明

  1. X-Vercel-Buffer-Response:这是Vercel专属响应头,设置为false会强制Serverless Functions实时发送响应内容,而非缓冲到执行结束。
  2. 响应头配置:明确内容类型为HTML并禁用缓存,避免浏览器或CDN中间节点缓冲内容,确保流式内容实时到达前端。
  3. HTML结构输出:将基础HTML标签放在函数最开始仅输出一次,避免在每个data事件中重复写入,导致页面结构混乱。
  4. 错误处理:添加流错误监听与全局异常捕获,确保异常情况下能正确关闭HTML标签并结束响应,避免连接挂起。

内容的提问来源于stack exchange,提问作者And Bast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 01:12:17