
本文详解如何在 php 中正确配置 curl 和输出缓冲,实现实时接收并逐块输出 openai api 的流式响应(stream=true),避免等待完整响应,提升用户体验。
本文详解如何在 php 中正确配置 curl 和输出缓冲,实现实时接收并逐块输出 openai api 的流式响应(stream=true),避免等待完整响应,提升用户体验。
OpenAI 的 Completion API 支持 stream: true 参数,返回以 text/event-stream 格式分块推送的 Server-Sent Events(SSE)。但 PHP 默认启用输出缓冲和压缩机制,导致数据被缓存、延迟输出,无法实现真正的“边接收边渲染”。要实现真正的流式响应,需同时从 PHP 运行时 和 cURL 处理逻辑 两层进行精细化控制。
✅ 关键配置三要素
-
禁用 PHP 输出缓冲与压缩
在脚本开头强制关闭缓冲和 zlib 压缩,确保 echo 立即发送到客户端:
<?php
// 必须置于脚本最顶部(早于任何输出)
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
@ob_end_clean(); // 清空并关闭当前输出缓冲区⚠️ 注意:ob_end_clean() 仅对当前激活的缓冲区生效;若使用框架或全局缓冲(如 ob_start()),需确保其已被清除或未启用。
-
自定义 cURL 写入回调函数(CURLOPT_WRITEFUNCTION)
替代 CURLOPT_RETURNTRANSFER(它会阻塞直到完成),改用回调函数实时处理每批次到达的原始字节流:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // 关键:禁用返回值捕获
curl_setopt($ch, CURLOPT_HEADER, false); // 避免响应头干扰解析
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) {
// SSE 数据格式为:data: {...}\n\n
echo $data;
// 强制刷新:填充空白防止浏览器缓冲(兼容 Chrome/Firefox)
echo str_repeat(' ', 1024);
flush(); // 推送至 Web 服务器
return strlen($data);
});? 说明:str_repeat(' ', 1024) 是经典技巧——多数浏览器(尤其 Chrome)要求单次响应 ≥ 1KB 才触发 JavaScript onmessage 或直接渲染;此填充确保流式内容即时可见。
-
服务端环境适配(可选但推荐)
若部署在 Nginx,需关闭代理缓冲与 gzip,否则 Nginx 可能缓存整个流:
# nginx.conf 或站点配置中
location /api/openai {
proxy_pass https://api.openai.com/v1/completions;
proxy_buffering off;
gzip off;
proxy_http_version 1.1;
proxy_set_header Connection '';
}✅ 完整可运行示例
<?php
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
@ob_end_clean();
function streamOpenAI($prompt = "Tell me about PHP") {
$OPENAI_API_KEY = 'your-api-key-here';
$data = [
'model' => 'text-davinci-002',
'prompt' => $prompt,
'temperature' => 0.5,
'max_tokens' => 64,
'stream' => true,
'user' => 'demo-' . uniqid()
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.openai.com/v1/completions',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
"Authorization: Bearer $OPENAI_API_KEY"
],
CURLOPT_RETURNTRANSFER => false,
CURLOPT_HEADER => false,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_WRITEFUNCTION => function($curl, $data) {
echo $data . str_repeat(' ', 1024);
flush();
return strlen($data);
}
]);
curl_exec($ch);
curl_close($ch);
}
// 调用(需通过 Web 服务器访问,CLI 不适用)
header('Content-Type: text/event-stream; charset=utf-8');
header('Cache-Control: no-cache');
streamOpenAI();? 注意事项与最佳实践
- 仅限 Web 环境:流式响应依赖 HTTP 协议特性,无法在 CLI 模式下生效。
- 前端配合:客户端建议使用 EventSource 或 fetch().readableStream 解析 SSE 格式,提取 data: 字段中的 JSON。
- 错误处理增强:生产环境应添加 curl_error()、HTTP 状态码校验(如 curl_getinfo($ch, CURLINFO_HTTP_CODE))及超时设置(CURLOPT_TIMEOUT)。
- 模型兼容性:text-davinci-002 已逐步弃用,推荐迁移到 gpt-3.5-turbo(需改用 Chat Completions API + messages 参数,流式结构略有不同)。
通过以上配置,你将获得真正低延迟、逐 token 渲染的 AI 响应体验——这是构建类 ChatGPT 交互界面的核心基础能力。
立即学习“PHP免费学习笔记(深入)”;



















