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

Laravel项目中AWS Lambda实现OpenAI流式响应失败求助

Laravel部署AWS Lambda后OpenAI流式响应失效的排查与修复

问题背景

在Laravel项目中尝试用AWS Lambda实现OpenAI流式响应,本地运行正常,但部署到Lambda后失效。已配置Lambda函数URL的CORS头部,问题仍存在。相关代码及配置如下:

适配AWS环境的代码

return response()->stream(function () use ($prompt) {
        if (ob_get_level() > 0) {
            ob_end_flush();
        }
        
        header('Lambda-Runtime-Function-Response-Mode: streaming');
        header('Transfer-Encoding: chunked');
    
        $stream = OpenAI::chat()->createStreamed([
            'model' => 'gpt-3.5-turbo',
            'messages' => $prompt['messages'],
            'presence_penalty' => 0.6,
            'frequency_penalty' => 0
        ]);
    
        foreach ($stream as $response) {
            if (isset($response['choices'][0]['delta']['content'])) {
                $message = $response['choices'][0]['delta']['content'];
                $messageFix = str_replace(["\n", "\r", "\r\n"], "<br/>", $message);
    
                echo dechex(strlen($messageFix)) . "\n";
                echo $messageFix . "\n";
    
                if (ob_get_level() > 0) {
                    ob_flush();
                    flush();
                }
    
                usleep(5000);
            }
    
            if (connection_aborted()) {
                break;
            }
        }
    
        echo "0\n\n";
        if (ob_get_level() > 0) {
            ob_flush();
            flush();
        }
    }, 200, [
        'Cache-Control' => 'no-cache',
        'X-Accel-Buffering' => 'no',
        'Content-Type' => 'text/event-stream',
    ]);   

本地运行正常的旧代码

return response()->stream(function () use ($prompt) {
    $stream = OpenAI::chat()->createStreamed([
        'model' => 'gpt-3.5-turbo',
        'messages' => $prompt['messages'],
        'presence_penalty' => 0.6,
        'frequency_penalty' => 0
    ]);

    $output = "";
    $responsedText = "";

    foreach ($stream as $response){
        if (isset($response['choices'][0]['delta']['content'])){
            $message = $response['choices'][0]['delta']['content'];
            $messageFix = str_replace(["\n", "\r", "\r\n"], "<br/>", $message);
            $output .= $messageFix;
            $responsedText .= $message;
            $string_length = Str::length($messageFix);
            $needChars = 6000-$string_length;
            $random_text = Str::random($needChars);
            echo PHP_EOL;
            echo 'data: ' . $messageFix.'/**'.$random_text."\n\n";
            ob_flush();
            flush();
            usleep(5000);
        }
        if (connection_aborted()) {
            break;
        }
    }
    echo 'data: [DONE]';
    echo "\n\n";
    ob_flush();
    flush();
    usleep(50000);
}, 200, [
    'Cache-Control' => 'no-cache',
    'X-Accel-Buffering' => 'no',
    'Content-Type' => 'text/event-stream',
]);

CORS配置

  • 暴露头部:content-type, connection, cache-control
  • 允许头部:content-type, connection, cache-control, x-custom-header

解决方案

1. 调整Lambda流式响应头部设置方式

不要在stream回调中手动调用header()添加Lambda-Runtime-Function-Response-Mode,Laravel的response()->stream()会统一处理响应头部,手动添加可能被覆盖或不生效。直接将该头部移到响应的头部数组中。

2. 移除手动设置的Transfer-Encoding头部

Lambda流式响应会自动处理分块编码,手动设置Transfer-Encoding: chunked会导致格式冲突,直接移除即可。

3. 修正分块输出的换行符规范

HTTP分块编码要求用\r\n(CRLF)作为分隔符,原代码中的换行符不符合规范,会导致Lambda无法正确识别分块。

4. 保持SSE格式输出(匹配前端解析逻辑)

本地代码输出的是SSE格式(data: ...\n\n),适配Lambda的代码改成了直接分块输出内容,前端无法解析。需要保持SSE格式的输出,同时适配Lambda的流式要求。

修改后的代码示例

return response()->stream(function () use ($prompt) {
    // 彻底关闭所有输出缓冲
    while (ob_get_level() > 0) {
        ob_end_flush();
    }

    $stream = OpenAI::chat()->createStreamed([
        'model' => 'gpt-3.5-turbo',
        'messages' => $prompt['messages'],
        'presence_penalty' => 0.6,
        'frequency_penalty' => 0
    ]);

    foreach ($stream as $response) {
        if (isset($response['choices'][0]['delta']['content'])) {
            $message = $response['choices'][0]['delta']['content'];
            $messageFix = str_replace(["\n", "\r", "\r\n"], "<br/>", $message);
            
            // 构造符合SSE规范的输出内容
            $sseData = "data: {$messageFix}\n\n";
            
            // 按照Lambda流式要求输出分块:十六进制长度 + CRLF + 内容 + CRLF
            echo dechex(strlen($sseData)) . "\r\n";
            echo $sseData . "\r\n";
            
            ob_flush();
            flush();
            
            usleep(5000);
        }

        if (connection_aborted()) {
            break;
        }
    }

    // 输出结束分块,标志流式响应完成
    echo "0\r\n\r\n";
    ob_flush();
    flush();
}, 200, [
    'Cache-Control' => 'no-cache',
    'X-Accel-Buffering' => 'no',
    'Content-Type' => 'text/event-stream',
    'Lambda-Runtime-Function-Response-Mode' => 'streaming'
]);

额外排查点

  • Lambda网络权限:确认Lambda函数的执行角色有访问OpenAI API的权限,若部署在私有子网需配置NAT网关确保互联网访问。
  • CORS配置验证:检查Lambda函数URL的CORS设置是否允许text/event-stream类型的请求,同时确认暴露的头部包含Content-Type和Cache-Control。
  • OpenAI客户端适配:验证OpenAI SDK在Lambda环境下能正确处理流式响应,必要时调整客户端超时时间或代理配置。

内容的提问来源于stack exchange,提问作者Thomas Chirwa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:34:54