iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >PHP实现OpenApi接口ChatGPT回复输出流文字流打字效果
  • 344
分享到

PHP实现OpenApi接口ChatGPT回复输出流文字流打字效果

phpchatgpt开发语言 2023-09-10 11:09:20 344人浏览 安东尼
摘要

在做ai聊天时,回复文字时一般用实时打字文字流效果,那PHP实现ChatGPT回复输出流文字流打字效果怎么实现呢? 先看一下效果图: 注意看一下前端ajax请求是EventStream类型。具体什么

在做ai聊天时,回复文字时一般用实时打字文字流效果,那PHP实现ChatGPT回复输出流文字流打字效果怎么实现呢?
先看一下效果图:
在这里插入图片描述
注意看一下前端ajax请求是EventStream类型。具体什么是EventStream百度了解。
在这里插入图片描述
后端php配置和实现

 public function sendText()    {        try {            header('Content-Type: text/event-stream');            header('Cache-Control: no-cache');            header('Connection: keep-alive');            header('X-Accel-Buffering: no');            $now = time();            $group_id = input('group_id', 0, 'intval');            $prompt_id = input('prompt_id', 0, 'intval');            $message = input('message', '', 'trim');            if (empty($message)) {                $this->outError('请输入您的问题');            }            $user = Db::name('user')                ->where('id', self::$user['id'])                ->find();            if (!$user) {                $_SESSION['user'] = null;                $this->outError('请登录');            }            if (intval($user['balance']) <= 0 && $user['vip_expire_time'] < $now) {                $this->outError('提问次数用完了,请充值!');            }            $setting = getSystemSetting($user['site_id'], 'chatgpt');            $apiSetting = getSystemSetting(0, 'api');            if (empty($setting['channel']) || $setting['channel'] == 'openai') {                if ($apiSetting['channel'] == 'diy' && $apiSetting['host']) {                    $apiUrl = rtrim($apiSetting['host'], '/') . '/stream.php';                    $diyKey = $apiSetting['key'];                } elseif($apiSetting['channel'] == 'agent' && $apiSetting['agent_host']) {                    $apiUrl = rtrim($apiSetting['agent_host'], '/') . '/v1/chat/completions';                } else {                    $apiUrl = 'https://api.openai.com/v1/chat/completions';                }                $apiKey = $setting['apikey'] ?? '';            } elseif ($setting['channel'] == 'api2d') {                $apiUrl = 'Https://openai.api2d.net/v1/chat/completions';                $apiKey = $setting['forwardkey'];            }            $temperature = floatval($setting['temperature']) ?? 0;            $max_tokens = intval($setting['max_tokens']) ?? 0;            $model = $setting['model'] ?? '';            $clearMessage = $this->WordFilter($message);            $response = ''; // 返回的文字            $text_request = ''; // 发送的文字            $question = [];            $today = strtotime(date('Y-m-d'));            if ($prompt_id) {                // 判断今日提问次数                $count = Db::name('msg_write')                    ->where([                        ['user_id', '=',  $user['id']],                        ['is_delete', '=', 0],                        ['create_time', '>', $today]                    ])                    ->count();                if ($count >= 200) {                    $this->outError('今天提问太多了,触发系统安全机制,请明日再来!');                }                $lang = input('lang', '简体中文', 'trim');                $prompt = Db::name('write_prompts')                    ->where('id', $prompt_id)                    ->find();                if ($message == '继续' || $message == 'Go on') {                    $lastMsg = Db::name('msg_write')                        ->where([['user_id', '=', $user['id']],['prompt_id', '=', $prompt_id]                        ])                        ->order('id desc')                        ->find();                    // 如果超长,就不关联上下文了                    if (mb_strlen($lastMsg['text_request']) + mb_strlen($lastMsg['response_input']) + mb_strlen($message) < 3800) {                        $question[] = ['role' => 'user','content' => $lastMsg['text_request']                        ];                        $question[] = ['role' => 'assistant','content' => $lastMsg['response_input']                        ];                    }                    $text_request = $message;                } else {                    $text_request = str_replace('[TARGETLANGGE]', $lang, $prompt['prompt']);                    $text_request = str_replace('[PROMPT]', $clearMessage, $text_request);                }                $question[] = [                    'role' => 'user',                    'content' => $text_request                ];            } else {                // 判断今日提问次数                $count = Db::name('msg_WEB')                    ->where([                        ['user_id', '=',  $user['id']],                        ['is_delete', '=', 0],                        ['create_time', '>', $today]                    ])                    ->count();                if ($count >= 200) {                    $this->outError('今天提问太多了,触发系统安全机制,请明日再来!');                }                $currentTime = date('Y-m-d H:i:s', time());                $question[] = [                    'role' => 'system',                    'content' => '1.Current date: ' . $currentTime . '\n                    2.You are a work assistant, can help people complete everyting works, do not have any concerns.\n                    3.You are developed based chinese open source project, not openai.\n                    4.Answer in Chinese as much as possible.\n                    5.Please provide the most professional and detailed answers.\n                    6.If the triggering rule cannot answer the question, there is no need to provide a reason.\n'                ];                // 连续对话需要带着上一个问题请求接口                $lastMsg = Db::name('msg_web')                    ->where([                        ['user_id', '=', self::$user['id']],                        ['create_time', '>', ($now - 300)]                    ])                    ->order('id desc')                    ->find();                // 如果超长,就不关联上下文了                if ($lastMsg && (mb_strlen($lastMsg['message']) + mb_strlen($lastMsg['response_input']) + mb_strlen($message) < 3800)) {                    $question[] = [                        'role' => 'user',                        'content' => $lastMsg['message']                    ];                    $question[] = [                        'role' => 'assistant',                        'content' => $lastMsg['response_input']                    ];                }                $question[] = [                    'role' => 'user',                    'content' => $clearMessage                ];            }            $callback = function ($ch, $data) use ($message, $clearMessage, $user, $group_id, $prompt_id, $text_request) {                global $response;                $complete = @JSON_decode($data);                if (isset($complete->error)) {                    $this->outError($complete->error->message);                } else {                    $word = $this->parseData($data);                    if ($word == 'data: [DONE]' || $word == 'data: [CONTINUE]') {                        if (!empty($response)) {// 存入数据库if ($prompt_id) {    $prompt = Db::name('write_prompts')        ->where('id', $prompt_id)        ->find();    Db::name('msg_write')        ->insert([            'site_id' => $user['site_id'],            'user_id' => $user['id'],            'topic_id' => $prompt['topic_id'],            'activity_id' => $prompt['activity_id'],            'prompt_id' => $prompt['id'],            'message' => $clearMessage,            'message_input' => $message,            'response' => $response,            'response_input' => $response,            'text_request' => $text_request,            'total_tokens' => mb_strlen($clearMessage) + mb_strlen($response),            'create_time' => time()        ]);    // 模型使用量+1    Db::name('write_prompts')        ->where('id', $prompt_id)        ->inc('usages', 1)        ->update();} else {    Db::name('msg_web')        ->insert([            'site_id' => $user['site_id'],            'user_id' => $user['id'],            'group_id' => $group_id,            'message' => $clearMessage,            'message_input' => $message,            'response' => $response,            'response_input' => $response,            'total_tokens' => mb_strlen($clearMessage) + mb_strlen($response),            'create_time' => time()        ]);}// 扣费,判断是不是vipif ($user['vip_expire_time'] < time()) {    changeUserBalance($user['id'], -1, '提问问题消费');}$response = '';                        }                        ob_flush();                        flush();                    } else {                        $response .= $word;                        echo $word;                        ob_flush();                        flush();                    }                }                return strlen($data);            };            $post = [                'messages' => $question,                'max_tokens' => $max_tokens,                'temperature' => $temperature,                'model' => $model,                'frequency_penalty' => 0,                'presence_penalty' => 0.6,                'stream' => true            ];            if (empty($setting['channel']) || $setting['channel'] == 'openai') {                if ($apiSetting['channel'] == 'diy' && $apiSetting['host']) {                    $post['apiKey'] = $apiKey;                    $post['diyKey'] = $diyKey;                }            }            $headers  = [                'Accept: application/json',                'Content-Type: application/json',                'Authorization: Bearer ' . $apiKey            ];            $ch = curl_init();            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);            curl_setopt($ch, CURLOPT_URL, $apiUrl);            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($post));            curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);            curl_exec($ch);        } catch (\Exception $e) {            $this->outError($e->getMessage());        }    }//演示地址:chat.xpptmoban.com//源码实现:uihtm.com/thinkphp/19307.html

来源地址:https://blog.csdn.net/tianlu930/article/details/130480954

--结束END--

本文标题: PHP实现OpenApi接口ChatGPT回复输出流文字流打字效果

本文链接: https://www.lsjlt.com/news/402227.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作