PHP对接阿里通义 AI 大模型,以SSE方式流式输出

首先要获取阿里云百炼的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;
### 将OpenAI阿里通义千问集成 为了实现OpenAI服务与阿里通义千问API和SDK的集成,开发者可以采取如下策略: #### 使用场景分析 在实际应用中,可能希望利用OpenAI的强大自然语言处理能力和特定功能的同时,借助阿里云平台的优势来增强应用程序的功能和服务质量。例如,在构建聊天机器人时,可以通过调用OpenAI接口获取高质量的回答模板或对话管理逻辑;而通过阿里云的服务,则可以获得更贴近本地化需求的支持以及更好的性能优化。 #### 技术方案概述 对于想要将两者结合起来使用的项目来说,主要的技术挑战在于如何有效地协调两个不同提供商之间的交互流程并确保数据传输的安全性和一致性。具体而言,可以从以下几个方面入手解决这个问题[^1]: - **身份验证机制**:由于涉及到跨服务商的数据交换,因此必须建立可靠的身份认证体系以保护敏感信息不被泄露。 - **请求转发模式**:考虑设计一种中间层架构用于接收来自客户端的应用程序编程接口(API)请求,并根据业务规则决定将其转交给哪个后端处理器——即要么是发送给OpenAI完成某些任务后再返回结果给用户界面(UI),亦或是直接由阿里云负责处理整个过程中的大部分工作量。 - **异步通信协议**:鉴于网络延迟等因素的影响,建议采用基于消息队列的消息传递方式来进行长时间运行的任务调度,从而提高系统的响应速度和用户体验满意度。 #### 实现方法举例 下面给出一段Python代码片段作为示例说明如何发起一次针对OpenAI Chat Completions API的HTTP POST请求并将得到的结果提交至阿里云上的某个自定义函数计算实例执行进一步操作: ```python import requests from aliyunsdkcore.client import AcsClient from aliyunsdkcore.request import CommonRequest def call_openai_chat_completion(prompt_text): url = "https://api.openai.com/v1/chat/completions" headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer YOUR_OPENAI_API_KEY' } payload = {"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": prompt_text}]} response = requests.post(url=url, json=payload, headers=headers).json() return response['choices'][0]['message']['content'] client = AcsClient('your-access-key-id', 'your-secret-access-key', 'cn-hangzhou') request = CommonRequest() request.set_accept_format('json') request.set_domain('functioncompute.cn-hangzhou.aliyuncs.com') request.set_method('POST') request.set_version('2019-07-24') request.set_action_name('InvokeFunction') request.add_query_param('ServiceName', 'my-service-name') request.add_query_param('FunctionName', 'process-openai-response') response_from_openai = call_openai_chat_completion("Tell me about today's weather.") request.add_body_params('Payload', {'inputText': response_from_openai}) result = client.do_action_with_exception(request) print(str(result)) ``` 此段脚本展示了怎样先向OpenAI发出询问天气状况的信息查询命令,再把获得的文字描述传送给部署于阿里云计算环境下的指定服务器端点做后续加工处理的过程[^2]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值