openAI 通过php方式 发送请求,流数据形式传输,php 实现chatGPT功能

这篇具有很好参考价值的文章主要介绍了openAI 通过php方式 发送请求,流数据形式传输,php 实现chatGPT功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

PHP调用OpenAI API的方法

此处使用的框架是 symfony ,可自行根据自己框架开发,大同小异,框架无所谓,主要是功能!
先上代码文章来源地址https://www.toymoban.com/news/detail-805430.html

<?php
namespace LdWxappPlugin\Api\Resource\Chatapi;
use ApiBundle\Api\ApiRequest;
use ApiBundle\Api\Resource\AbstractResource;
use ApiBundle\Api\Annotation\ApiConf;
use AppBundle\Common\ArrayToolkit;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class ChatapiConversation extends AbstractResource
{
   
    protected $host = 'http://*.*.*.*'; // 服务器地址
    protected $uri = '/v1/chat/completions'; // 调用的接口地址
    protected $authKey = 'Basic c2VjcmV********'; // api鉴权的key
    protected $message = '';
    protected $sources = [];
    protected $conversationId = ''; 
    protected $currentMessage='';
    /**
     * @var array|mixed
     */
    private $document;
    /**
     * @param ApiRequest $request
     * @param $conversationId 会话id
     */
     // 前端输入完信息,发送时调用的请求
    public function add(ApiRequest $request,$conversationId)
    {
   
        $this->verifySend();
        $this->conversationId = $conversationId;
        //刷新缓冲区
        ob_implicit_flush(true);
        ob_end_flush();
        $response = new StreamedResponse();

        // 设置响应头,指定Content-Type为text/event-stream
        $response->headers->set('Content-Type', 'text/event-stream');
        $response->headers->set('Cache-Control', 'no-cache');
        $response->headers->set('Charset', 'UTF-8');
        $response->headers->set('X-Accel-Buffering', 'no');
        $params = $request->request->all();
        $aiParams = $this->filterAiParams($params);
        //插入用户消息
        $this->getChatApiConversationService()->addUserMessage($this->conversationId,$aiParams);
        // 设置响应内容生成器
        $response->setCallback(function () use ($request,$aiParams) {
   
            $this->forwardAiRequest($aiParams);
        });

        // 发送响应
        $response->send();
    }

    public function update(ApiRequest $request,$conversationId,$flag)
    {
   
        $params = $request->request->all();
        $message = $params['messages']['0']['content'] ?? '';
        $result = $this->getChatApiConversationService()->addAiMessage($conversationId,['message'=>$message],'');
        if ($result){
   
            return ['status'=>'success','message'=>'补充消息成功','code'=> 1,"data"=>['messageId'=>$result['id']] ];
        } else {
   
            return ['status'=>'fail','message'=>'补充消息成功','code'=> 0];
        }
    }

    /**
     * @param $chunk
     * @return string
     */
    public function formatAiResponse($chunk)
    {
   
        if($chunk == "Internal Server Error"){
   
            throw new BadRequestHttpException("AI好像开小差了~请联系客服");
        }


        //替换掉data:
        $chunkJsonStr = trim(str_replace('data:','',$chunk));
        $isComplete = json_decode($this->currentMessage,true);
        if($isComplete == null){
   
            $this->currentMessage .= $chunkJsonStr;
        } else {
   
            $this->currentMessage = $chunkJsonStr;
        }
        if($chunkJsonStr !='[DONE]'){
   
            //这里会出现单条消息超限多条消息拼接的情况,
            $chunkArr = json_decode($this->currentMessage,true);
            if (!$chunkArr){
   
                return null;
            }
            $this->currentMessage = '';
            $originMessage = $chunkArr['choices'][0]['delta']['content'] ?? '';
            //拼接当前条消息数据
            $this->message .= $originMessage;
            //赋值引用文档
            if($chunkArr['choices'][0]['sources']){
   
                $this->document = $chunkArr['choices'][0]['sources'];
            }

            //重新拼装前端结构
            $customChunkArr = ["status"=>"going","content"=>$originMessage];

            return "data: ".json_encode($customChunkArr,JSON_UNESCAPED_UNICODE)."\n\n";
        } else {
   
            //传输结束,这里处理数据入库$this->message
            
            $sources = $this->getTaskByPageLabel($this->document);
            $insertData = [
                'message' => $this->message,
                "sourceFrom" => json_encode($sources,JSON_UNESCAPED_UNICODE)
            ];
            //这里判断是否当前课程学员
            //先查出当前会话对应goods

            $conversation = $this->getChatApiService()->findByConversationId($this->conversationId);
            $isMember = false;
            $id = $conversation[0]['goodsId'] ?? 0;
            if($id !== 0){
   
                //查询当goods_
                $goodsApiRequest = new ApiRequest("/api/goods/{
     $id}", 'GET', []);
                try{
   
                    $goods = $this->container->get('api_resource_kernel')->handleApiRequest($goodsApiRequest);
                    $isMember = $goods['isMember'];
                }catch(\Exception $e){
   
                    $catchFlag = 1;
                }
            }
            //根据taskId查询task


            $originData = json_encode(['message'=>$this->message,'sources'=>$this->document],JSON_UNESCAPED_UNICODE);
            $result = $this->getChatApiConversationService()->addAiMessage($this->conversationId,$insertData,$originData);
            return "data: ".json_encode(["status"=>"done","finishData"=>['id'=>$result['id'],"sourceFrom"=>$sources,"isMember"=>$isMember]],JSON_UNESCAPED_UNICODE)."\n\n";
        }

    }

    //前置验证
    protected function verifySend()
    {
   
        $userId = $this->getCurrentUser()->getId();
        if (!$userId){
   
            //登录验证
            throw new BadRequestHttpException("请先登录");
        }
        $factory = $this->biz->offsetGet('ratelimiter.factory');
        $rateLimiter = $factory('chat_send_message', 5, 60);
        $remained = $rateLimiter->check($userId);
        if (!$remained) {
   
            throw new BadRequestHttpException("发送过于频繁请于1分钟后重试");
        }
    }

    public function filterAiParams($params)
    {
   
        if(!$params['messages'] || $params['conversationId']){
   
            throw new BadRequestHttpException("缺失必要参数");
        }
        $params['stream'] = true;
        $params['use_context'] = true;
        $params['include_sources'] = true;
        return $params;
    }


    public function forwardAiRequest($params)
    {
   
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $this->host.$this->uri,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => json_encode($params),
            CURLOPT_HTTPHEADER => array(
                'Accept: application/json',
                'Authorization: '.$this->authKey,
                'Content-Type: application/json'
            ),
            // 启用流式传输模式
        ));
        curl_setopt($curl, CURLOPT_BUFFERSIZE, 16384);
        curl_setopt($curl, CURLOPT_WRITEFUNCTION, function ($ch, $chunk) {
   
            // 处理接收到的流式数据
            $echoStream = $this->formatAiResponse($chunk);
            if ($echoStream != null){
   
                echo $echoStream;
            }
            flush();
            return strlen($chunk);
        });
        $response = curl_exec($curl);
        curl_close($curl);
        // echo $response;
    }


    //根据map,page_label获取task
    protected function getTaskByPageLabel($sources)
    {
   
        $tasks = [];
        if($sources){
   
            foreach ($sources as $source){
   
                $pageLabel = $source['document']['doc_metadata']['page_label'] ?? 0;
                $score = $source['score'] ?? 0;
                if ($pageLabel && $score>0.5){
   
                    $task = self::getPageTaskMap()[$pageLabel];
                    $taskInfo = $this->getTaskService()->getTask($task['taskId']);
                    $task['courseId'] = $taskInfo['courseId'];
                    $tasks[] = $task;
                }
            }
        }
        return array_unique($tasks);
    }


    //page与task映射map,先写死实现功能
    static protected function getPageTaskMap()
    {
   
        //page_label => taskInfo
        return  [
            1 => [
                'taskId'=>51147,
                'taskTitle'=>"课时1:课程概述、特点及说明",
            ],
            2 => [
                'taskId'=>51148,
                'taskTitle'=>"课时2:资产配置概述、均值方差模型配置法的 GPT 应用",
            ],
            3 => [
                'taskId'=>51148,
                'taskTitle'=>"课时2:资产配置概述、均值方差模型配置法的 GPT 应用",
            ],
            4 => [
                'taskId'=>51148,
                'taskTitle'=>"课时2:资产配置概述、均值方差模型配置法的 GPT 应用",
            ],
            5 => [
                'taskId'=>51149,
                'taskTitle'=>"课时3:Black-Litterman 策略、风险平价策略介绍及GPT 应用",
            ],
            6 => [
                'taskId'=>51149,
                'taskTitle'=>"课时3:Black-Litterman 策略、风险平价策略介绍及GPT 应用",
            ],
            7 => [
                'taskId'=>51149,
                'taskTitle'=>"课时3:Black-Litterman 策略、风险平价策略介绍及GPT 应用",
            ],
            8 => [
                'taskId'=>51150,
                'taskTitle'=>"课时4:Black-Litterman 策略、风险平价策略介绍及GPT 应用",
            ],
            9 => [
                'taskId'=>51150,
                'taskTitle'=>"课时4:Black-Litterman 策略、风险平价策略介绍及GPT 应用",
            ],
            10 => [
                'taskId'=>51151,
                'taskTitle'=>"课时5:基金分类、标签体系、收益风险指标分析",
            ],
            11 => [
                'taskId'=>51151,
                'taskTitle'=>"课时5:基金分类、标签体系、收益风险指标分析",
            ],
            12 => [
                'taskId'=>51152,
                'taskTitle'=>"课时6:基金投资体验分析和投资风格分析",
            ],
            13 => [
                'taskId'=>51152,
                'taskTitle'=>"课时6:基金投资体验分析和投资风格分析",
            ],
            14 => [
                'taskId'=>51152,
                'taskTitle'=>"课时6:基金投资体验分析和投资风格分析",
            ],
            15 => [
                'taskId'=>51153,
                'taskTitle'=>"课时7:基金插件工具介绍及营销文案编写",
            ],
            16 => [
                'taskId'=>51154,
                'taskTitle'=>"课时8:历史事件复盘",
            ],
            17 => [
                'taskId'=>51155,
                'taskTitle'=>"课时9:近期市场、经济复盘",
            ],
            18 => [
                'taskId'=>51156,
                'taskTitle'=>"课时10:未来经济展望",
            ],
            20 => [
                'taskId'=>51157,
                'taskTitle'=>"课时11:PPI 时间序列预测",
            ],
            21 => [
                'taskId'=>51158,
                'taskTitle'=>"课时12:周期划分到策略适配",
            ],
            22 => [
                'taskId'=>51174,
                'taskTitle'=>"课时13:金融数据分析简介",
            ],
            23 => [
                'taskId'=>51175,
                'taskTitle'=>"课时14:调研问卷分析案例",
            ],
            24 => [
                'taskId'=>51175,
                'taskTitle'=>"课时14:调研问卷分析案例",
            ],
            25 => [
                'taskId'=>51176,
                'taskTitle'=>"课时15:金融客户机器学习分群案例",
            ],
            26 => [
                'taskId'=>51176,
                'taskTitle'=>"课时15:金融客户机器学习分群案例",
            ],
            27 => [
                'taskId'=>51177,
                'taskTitle'=>"课时16:财经公众号内容提取案例",
            ],
            28 => [
                'taskId'=>51178,
                'taskTitle'=>"课时17:筛选符合减持新规的股票",
            ],
            29 => [
                'taskId'=>51159,
                'taskTitle'=>"课时18:数据提取:基金历史业绩(附 Noteable 插件介绍)",
            ],
            30 => [
                'taskId'=>51159,
                'taskTitle'=>"课时18:数据提取:基金历史业绩(附 Noteable 插件介绍)",
            ],
            31 => [
                'taskId'=>51160,
                'taskTitle'=>"课时19:数据提取:基金基础信息",
            ],
            32 => [
                'taskId'=>51161,
                'taskTitle'=>"课时20:数据提取:基金基础信息",
            ],
            33 => [
                'taskId'=>51162,
                'taskTitle'=>"课时21:数据分析:持仓数据图表化",
            ],
            34 => [
                'taskId'=>51163,
                'taskTitle'=>"课时22:数据分析:持仓数据分析",
            ],
            35 => [
                'taskId'=>51163,
                'taskTitle'=>"课时22:数据分析:持仓数据分析",
            ],
            36 => [
                'taskId'=>51164,
                'taskTitle'=>"课时23:数据分析:文字描述生成",
            ],
            37 => [
                'taskId'=>51165,
                'taskTitle'=>"课时24:数据分析:大类资产配比计算及增配建议",
            ],
            38 => [
                'taskId'=>51166,
                'taskTitle'=>"课时25:数据分析:基金持仓行业分布",
            ],
            39 => [
                'taskId'=>51167,
                'taskTitle'=>"课时26:内容生成:宏观经济与市场分析(及 KeyMate插件介绍)",
            ],
            40 => [
                'taskId'=>51167,
                'taskTitle'=>"课时26:内容生成:宏观经济与市场分析(及 KeyMate插件介绍)",
            ],
            41 => [
                'taskId'=>51168,
                'taskTitle'=>"课时27:内容生成:行业分析",
            ],
            42 => [
                'taskId'=>51169,
                'taskTitle'=>"课时28:内容生成:基金分析",
            ],
            43 => [
                'taskId'=>51170,
                'taskTitle'=>"课时29:风格适配:结构化 Prompt",
            ],
            44 => [
                'taskId'=>51171,
                'taskTitle'=>"课时30:风风格适配:Custom Instructions",
            ],
            45 => [
                'taskId'=>51172,
                'taskTitle'=>"课时31:风风格适配:Custom Instructions",
            ],
            46 => [
                'taskId'=>51173,
                'taskTitle'=>"课时 32: 资产配置报告展示",
            ],
            47 => [
                'taskId'=>51173,
                'taskTitle'=>"课时 32: 资产配置报告展示",
            ],

        ];
    }

    protected function getTaskService()
    {
   
        return $this->service('Task:TaskService');
    }

    private function getProdu

到了这里,关于openAI 通过php方式 发送请求,流数据形式传输,php 实现chatGPT功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Shell脚本实现SFTP传输文件,通过密码形式

    cat 读取文件内容 grep server : 查找文件内容中包含server字符的,行内容 awk -F ‘=’ :实现字符串分割,分割字符’‘=’ ${print $2}: 其中$2 表示切割后数组中第几值 base -d :解码base64字符串,转为可识别字符串

    2024年02月12日
    浏览(14)
  • 使用HTTP方式发送请求及json数据的接收和解析

    使用HTTP方式发送请求及json数据的接收和解析

    目录 需求 请求端 1,添加依赖 2,请求对象 3,请求工具类 4,请求测试(事先开启接收端的服务) 接收端 数据请求模拟 本项目需要通过向对端第三方项目发送一个http的post类型的请求,并且指定了一些请求字段,数据传输采用了json,对请求头没有其他特殊要求,所以这里写

    2024年01月17日
    浏览(83)
  • PHP的curl有三种Post请求数据的方式

    今天要讲的HTTP请求头的Content-Type字段,就是在curl发送post请求的时候需要指定以何种方式来请求数据,常用的有3类: 1、form-data 。就是 multipart/form-data 使用表单的方式来发送数据 是curl采用的默认发送方式。请求数组类型的格式。 Content-Type: multipart/form-data 2、x-www-form-urlenco

    2024年02月11日
    浏览(23)
  • SAP 通过配置传输的方式恢复某个CLIENT下的基础配置数据

    SAP 通过配置传输的方式恢复某个CLIENT下的基础配置数据

    SAP 通过配置传输的方式恢复某个 CLIENT 下的基础配置数据     比如某个项目上用户不小心误操作,将 SAP 系统标准的物料类型全部删除了(事务代码 OMS2) 。这导致系统无法继续使用了,需要采取技术手段将删除的数据恢复过来。   解决方案也很简单 , 换一个 Client, 进入这个

    2024年04月28日
    浏览(6)
  • 用java实现模仿 Postman 发送 form-data 形式的请求,并指定编码格式

    可以使用 Apache HttpClient 库来模仿 Postman 发送 form-data 形式的请求,并指定编码格式。以下是一个示例代码: 在这个示例中, YOUR_ENDPOINT_URL 应该被替换为目标 URL。这段代码使用了 Apache HttpClient 库创建了一个带有 form-data 的请求,并使用 UrlEncodedFormEntity 设置了编码格式为 UTF-

    2024年02月02日
    浏览(17)
  • 138. 第三方系统或者工具通过 HTTP 请求发送给 ABAP 系统的数据,应该如何解析

    138. 第三方系统或者工具通过 HTTP 请求发送给 ABAP 系统的数据,应该如何解析

    本教程第 37 篇文章,我们介绍了如何在 SAP ABAP 系统 SICF 事务码 里,开发一段 ABAP 代码,用来响应通过浏览器或者第三方工具,比如 curl,Postman 发起的 HTTP 请求。 31. 如何让 ABAP 服务器能够响应通过浏览器发起的自定义 HTTP 请求 在实际的 ABAP 集成项目中,这种方式非常使用。

    2024年03月21日
    浏览(53)
  • 微信小程序可以通过wx.request()方法发送text/event-stream请求头的数据,并通过wx.onSocketMessage()方法动态接收数据

    具体步骤如下: 1. 使用wx.request()方法发送text/event-stream请求头的数据,示例代码如下: ``` wx.request({   url: \\\'your_url\\\',   header: {     \\\'Content-Type\\\': \\\'text/event-stream\\\'   },   success: function(res) {     console.log(res)   } }) ``` 2. 在页面onLoad()方法中创建WebSocket连接,示例代码如下: ``` onLoa

    2024年02月05日
    浏览(35)
  • php使用guzzle http发送并发接口请求

    在 PHP 中, Guzzle 是一个功能强大且流行的 HTTP 客户端,提供了方便的接口来发送 HTTP 请求并处理响应,本人非常喜欢这个包且重度依赖。 以下是使用 Guzzle 发送并发请求的基本示例: 

    2024年01月16日
    浏览(14)
  • 通过 HttpClient 发送请求

    通过 HttpClient 发送请求

    2024年02月12日
    浏览(11)
  • Windows11如何通过附近共享发送文件,附近共享传输文件到电脑

    Windows11如何通过附近共享发送文件,附近共享传输文件到电脑

      Windows11如何通过附近共享发送文件 ?2018年,微软推出了名为Nearear Share(附近共享)的新功能。Near share是一种在PC之间传输文件的新方式,类似Airdrop的功能,只需要开启蓝牙和WiFi就能分享照片/影片/文件给另一台电脑,无须传输线、USB或者线上的网络空间分享档案!这也是

    2024年02月05日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包