Index.php 5.9 KB
<?php
declare (strict_types = 1);

namespace app\chat\controller;
use app\chat\controller\Base;
use think\facade\Db;
use app\base\model\BaseModel;
use think\facade\View;
use think\facade\Cookie;

class Index extends Base
{
	public function index(){
		$verify = Cookie::get('verify',0);
		$agent = site_info();
		View::assign('verify',$verify);
		View::assign('agent',$agent);
		return View::fetch('chat@index/index');
	}

	public function getGroupChatMsg(){
		$group_id = $this->req->param('group_id');
		$uip = $this->req->ip();
		$where = [];
        $where[] = ['uip','=',$uip];
        $where[] = ['group_id','=',$group_id];

        $msgList = Db::table('kt_chat_msg')->field('id,message,response')->where($where)->order('id asc')->select();
        $msgs = [];
        foreach ($msgList as $key => $msg) {
        	$msgs[] = [
        		'role' => '我',
        		'content' => $msg['message']
        	];
        	$msgs[] = [
        		'role' => '助手',
        		'content' => $msg['response']
        	];
        }
        return success('获取成功',$msgs);
	}

	public function getGroupList(){
		$page = $this->req->param('page',1);
        $size = $this->req->param('size',10);
        $name = $this->req->param('name');
        $uip = $this->req->ip();
        $where = [];
        $where[] = ['uip','=',$uip];
        if($name) $where[] = ['name','like',"%{$name}%"];

        $res = Db::table('kt_chat_msg_group')->where($where);
        $data['count'] = $res->count();
        $data['item'] = $res->field('id,name')->order('id desc')->page($page, $size)->select()->toArray();
        if(!$name && empty($data['item'])){
        	$name = '新的会话';
        	$group_id = Db::table('kt_chat_msg_group')->insertGetId([
        		'uip' => $uip,
        		'name' => $name,
        		'c_time' => time()
        	]);
        	$data['item'] = [[
        		'id' => $group_id,
        		'name' => $name
        	]];
        	$data['count'] = 1;
        }
        return success('分组数据',$data);
	}

	public function addGroup(){
		$uip = $this->req->ip();
		$name = $this->req->param('name');
		if(!$name) return error('会话标题不能为空');
		$id = Db::table('kt_chat_msg_group')->insertGetId([
			'uip' => $uip,
			'name' => $name,
			'c_time' => time()
		]);
		return success('添加成功',$id);
	}

	public function editGroup(){
		$id = $this->req->param('id');
		if(!$id) return error('缺少必要参数');
		$name = $this->req->param('name');
		if(!$name) return error('会话标题不能为空');
		Db::table('kt_chat_msg_group')->where('id',$id)->update([
			'name' => $name
		]);
		return success('更新成功');
	}

	public function verifyPwd(){
		$pwd = $this->req->param('pwd');
		if($pwd != 'bronet') return error('密码错误');
		Cookie::forever('verify',1);
		return success('登录成功');
	}

	public function sendtext(){
		header('Content-Type: text/event-stream');
      	header('Cache-Control: no-cache');
      	header('Connection: keep-alive');
      	header('X-Accel-Buffering: no');

		$message = $this->req->param('message');
		$group_id = $this->req->param('group_id');
		$uip = $this->req->ip();
		if(!$message){
			echo 'data:[error]请输入您的问题\n\n';ob_flush();flush();exit;
		}
		$response = ''; // 返回的文字
		
		// 连续对话需要带着上一个问题请求接口
		$now = time();
		$lastMsg = Db::table('kt_chat_msg')->where([
			['uip', '=', $uip],
			['group_id', '=', $group_id],
			['c_time', '>', ($now - 300)]
		])->order('id desc')->find();
		// 如果超长,就不关联上下文了
		if ($lastMsg && (mb_strlen($lastMsg['message']) + mb_strlen($lastMsg['response']) + mb_strlen($message) < 3800)) {
			$messages[] = [
                'role' => 'user',
                'content' => $lastMsg['message']
            ];
            $messages[] = [
                'role' => 'assistant',
                'content' => $lastMsg['response']
            ];
		}
		$messages[] = [
			'role'=>'user',
			'content'=>$message
		];

		$uid = BaseModel::getUid();
		$config = Db::table('kt_base_gpt_config')->json(['openai','api2d'])->where('uid',$uid)->find();
		if($config){
			if($config['channel'] == 2){
				$aiconfig = $config['api2d'];
				$ktadmin = new \Ktadmin\Chatgpt\Ktadmin(['channel'=>2,'api_key'=>$aiconfig['forward_key'],'diy_host'=>'']);
			}else{
				$aiconfig = $config['openai'];
				$ktadmin = new \Ktadmin\Chatgpt\Ktadmin(['channel'=>1,'api_key'=>$aiconfig['api_key'],'diy_host'=>$aiconfig['diy_host']]);
			}
		}else{
			echo "data:[error]未检查到配置信息\n\n";ob_flush();flush();exit;
		}

		$ktadmin->chat()->sendText($messages, function($ch, $data) use($ktadmin,$message,$uip,$group_id) {
			global $response;
			$complete = @json_decode($data);
			if(isset($complete->error)){
				echo 'data:[error]'.$complete->error->message."\n\n";ob_flush();flush();exit;
			}elseif(@$complete->object == 'error'){
				echo 'data:[error]'.$complete->message."\n\n";ob_flush();flush();exit;
			}
			$word = $ktadmin->chat()->parseData($data);
			$word = str_replace("\n", '<br/>', $word);
			if($complete){//一次性完整输出
				if (!empty($word)) {
					Db::table('kt_chat_msg')->insert([
						'uip' => $uip,
						'group_id' => $group_id,
						'message' => $message,
						'response' => $word,
						'c_time' => time()
					]);
					echo "data:".$word."\n\n";
				}
				ob_flush();flush();
			}else{//流式
				if($word == 'data: [DONE]' || $word == 'data: [CONTINUE]'){
					if (!empty($response)) {
						Db::table('kt_chat_msg')->insert([
							'uip' => $uip,
							'group_id' => $group_id,
							'message' => $message,
							'response' => $response,
							'c_time' => time()
						]);
						$response = '';
					}
					ob_flush();flush();
				}else{
					$response .= $word;
					echo "data:".$word."\n\n";ob_flush();flush();
				}
			}
	        return strlen($data);
	    },['temperature'=>$aiconfig['temperature'],'max_tokens'=>$aiconfig['max_tokens'],'model'=>$aiconfig['model'],'stream'=>$aiconfig['stream']]);
		exit();
	}

}