首先要获取阿里云百炼的API KEY 和 模型id
具体PHP端代码如下:
//控制器端
public function questionAsk(Request $request)
{
$message = $request->input('message') ?? '';
// 上一轮对话的id
$session_id = $request->input('session_id') ?? '';
if(empty($message)){
return $this->failed('请输入问题');
}
$data = [
'prompt' => $message
];
if(!empty($session_id)){
$data['session_id'] = $session_id;
}
$AliAiService = new AliAiService();
$AliAiService->requestQuestion($data);
flush();
}
//AliAiService
<?php
namespace App\Http\Controllers\Plugin;
class AliAiService
{
protected string $apiKey;
protected string $application_id;
public function __construct()
{
$this->apiKey = '你的 API-KEY ';
$this->application_id = '你的模型id (deepseek或者其他模型)';
}
public function requestQuestion($data)
{
$application_id = $this->application_id;
$app_key = $this->apiKey;
//阿里百炼请求地址
$app_url = "https://dashscope.aliyuncs.com/api/v1/apps/$application_id/completion";
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no');
header('Connection: keep-alive');
header('Access-Control-Allow-Origin: *');
set_time_limit(0);
ob_end_clean();
ob_implicit_flush(1);
$headers = [
'Authorization: Bearer ' . $app_key,
'Content-Type: application/json',
'X-DashScope-SSE: enable'
];
$params = [
'input' => $data,
'parameters' => [
'result_format'=>'message',
'incremental_output'=>true
],
];
$ch = curl_init($app_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//有时候希望返回的内容作为变量储存,而不是直接输出。这个时候就必需设置curl的CURLOPT_RETURNTRANSFER选项为1或true。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);//设置这个选项为一个非零值(象 “Location: “)的头,服务器会把它当做HTTP头的一部分发送(注意这是递归的,PHP将发送形如 “Location: “的头)。
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//curl_exec()获取的信息以文件流的形式返回,而不是直接输出
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $data) {
$res = substr(explode("\n",$data)[3],5);
$res = json_decode($res,true);
if($res['output']){
// echo $res['output']['text'];
echo "data: " . json_encode($res['output'])."\n\n";
flush(); // 立即将输出发送到客户端
}else{
echo $res['message']. "\n\n";
flush(); // 立即将输出发送到客户端
}
return strlen($data);
});
curl_exec($ch);
curl_close($ch);
}
}
前端收到的流式内容
data: {"session_id":"36af37a95da04722a29191a7f2ae1d86","finish_reason":"null","text":"\u3002\u76f8\u4fe1\u81ea\u5df1\uff0c\u6bcf"}
data: {"session_id":"36af37a95da04722a29191a7f2ae1d86","finish_reason":"null","text":"\u4e00\u6b65\u52aa\u529b\u90fd\u5c06\u4e3a"}
data: {"session_id":"36af37a95da04722a29191a7f2ae1d86","finish_reason":"null","text":"\u5b9e\u73b0\u68a6\u60f3\u6dfb\u7816\u52a0\u74e6\u3002"}
data: {"session_id":"36af37a95da04722a29191a7f2ae1d86","finish_reason":"null","text":"\u52a0\u6cb9\u5427\uff0c\u672a\u6765\u5c5e\u4e8e\u90a3\u4e9b"}
data: {"session_id":"36af37a95da04722a29191a7f2ae1d86","finish_reason":"null","text":"\u6562\u4e8e\u8ffd\u68a6\u5e76\u4e3a\u4e4b"}
data: {"session_id":"36af37a95da04722a29191a7f2ae1d86","finish_reason":"null","text":"\u4e0d\u61c8\u594b\u6597\u7684\u4eba\uff01"}
data: {"session_id":"36af37a95da04722a29191a7f2ae1d86","finish_reason":"stop","text":""}
前端处理流式内容
// 分割 SSE 事件(按 \n\n 分割)
const events = buffer.split('\n\n');
buffer = events.pop() || ''; // 保留未完成部分
for (const event of events) {
//找出data: 然后替换成空字符串,拿到json字符串后转成json对象
if (event.startsWith('data: ')) {
const jsonStr = event.replace('data: ', '').trim();
try {
const data = JSON.parse(jsonStr);
console.log('收到数据:', data.text);
} catch (err) {
console.error('解析错误:', err);
}
}
}
PHP 还有另一种写法 ,这两种都大同小异,基本上是一样的
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no');
header('Connection: keep-alive');
header('Access-Control-Allow-Origin: *');
$api_key = '你的 API-KEY ';
$application_id = '你的模型id (deepseek或者其他模型)';
$api_url = "https://dashscope.aliyuncs.com/api/v1/apps/$application_id/completion";
$message = $request->input('message') ?? '';
if(empty($message)){
return $this->failed('请输入问题');
}
$headers = [
'Authorization: Bearer ' . $api_key,
'Content-Type: application/json',
'X-DashScope-SSE: enable'
];
$params = [
'input' => [
'prompt' => $message,
],
'parameters' => [
'result_format'=>'message',
'incremental_output'=>true
],
];
$callback = function($ch, $data) use ($log_id,$application_id){
$res = substr(explode("\n",$data)[3],5);
$res = json_decode($res,true);
if($res['output']){
echo "data: " . json_encode($res['output']) . "\n\n";
ob_flush();flush();
}
return strlen($data);
};
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
curl_exec($ch);
curl_close($ch);
exit;