PHP 中使用 cURL 调用流式接口模式+流式响应并返回给客户端(php对接通义千问流模式输出给客户端–亲测可行)

内容:

在 Web 开发中,流式响应(Streaming Response)是一种高效的数据传输方式,它允许服务器在数据完全生成之前就开始向客户端发送数据。这在处理大文件、实时数据或其他需要快速响应的场景中特别有用。结合 cURL 库,我们可以在 PHP 中实现流式响应,并通过 Server-Sent Events (SSE) 将数据实时推送给客户端。

本案例种php在服务端先充当客户端调用通义千问的流模式api(和普通api类似就是响应模式是流的形式),然后再充当服务端,同时开启流模式,实时输出给客户端,客户端暂时可用浏览器测试。

核心方法

/**
 * 流式请求--通过 cURL 发起流式请求并处理响应
 *
 * @param string $url 请求的 URL
 * @param array $headers 请求头数组
 * @param array|string|null $postData POST 数据
 * @param callable $callback 处理响应数据的回调函数
 * @throws Exception 如果回调函数不是有效的 Callable
 */
function curlStreamRequest(string $url,$postData = null, array $headers = [],  callable $callback) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // 不将响应保存为字符串,直接处理
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 注意:在生产环境中应启用 SSL 验证
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 注意:同上
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POST, is_array($postData) || !empty($postData));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $data) use ($callback) {
        // 调用回调函数处理数据
        $callback($data);
        return strlen($data); // 返回接收到的数据长度
    });

    // 执行请求并获取响应
    curl_exec($ch);

    // 检查是否有错误发生
    if (curl_errno($ch)) {
        throw new \Exception(curl_error($ch));
    }

    // 关闭 cURL 句柄
    curl_close($ch);
}

控制器中调用示例--我这个是fasadmin中api模块的写法

/******测试流式调用*************/
    public function  request_liu(){
        header('Content-Type: text/event-stream'); // 以事件流的形式告知浏览器进行显示
        header('Cache-Control: no-cache'); // 告知浏览器不进行缓存
        header('X-Accel-Buffering: no'); //关闭加速缓冲
        $url="https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
        $prompt=$this->request->param('prompt','今天天气真好,哈哈哈哈说的就是可对接上课');
        $json='{
    "model":"qwen-long",
    "messages":[
        {
            "role":"system",
            "content":"我希望你充当机器翻译用在文本翻译场景 ,你会检测语言语种,翻译它为简体中文,不需要和我对话,直接输出翻译结果即可,不需要解释."
        },
        {
            "role":"user",
            "content":"今天天气真好,哈哈哈哈说的就是可对接上课"
        }
    ],
    "stream":true
     }';
        $arr=json_decode($json,true);
        $arr['messages'][1]['content']=$prompt;
        $header=['Authorization: Bearer Bearer sk-xxxxxx','Content-Type: application/json'];
        /**
         * 示例回调函数,用于处理接收到的数据并返回给客户端
         *
         * @param string $data 接收到的数据片段
         */
        function handleResponseData($data) {
            // 在这里,你可以将数据写入输出缓冲区或直接发送给客户端-例如,使用 echo 或 SSE 发送数据
            //sleep(3);
            echo $data; // 假设这里直接将数据发送给客户端
            echo "\n";
            //刷新输出缓冲区---把数据输出给浏览器
            ob_flush();
            flush();
        }
        // 使用示例
        $res=curlStreamRequest(
            $url, // 替换为实际的 API URL
            json_encode($arr), // 替换为实际的 POST 数据(如果需要)
            $header, // 替换为实际的请求头
            //直接传递闭包函数
            function($data) {
             handleResponseData($data);
           }
           //'handleResponseData' // 传递回调函数名作为字符串(如果回调函数在全局作用域中)
        );

    }

备注:通义千问的key这里是乱填的,如需使用可以自己更换

亲测可行哈

THE END