179 lines
5.5 KiB
PHP
179 lines
5.5 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Jobs;
|
||
|
|
|
||
|
|
use App\Common\cache\redis\ApiRedisKey;
|
||
|
|
use App\Http\Response\ResponseJson;
|
||
|
|
use App\Models\App\UserTeam;
|
||
|
|
use App\Models\ChatMessage;
|
||
|
|
use App\Models\User;
|
||
|
|
use App\Models\UserGptConfig;
|
||
|
|
use App\Services\IMService;
|
||
|
|
use App\Services\LoveGPTService;
|
||
|
|
use GuzzleHttp\Client;
|
||
|
|
use Illuminate\Bus\Queueable;
|
||
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||
|
|
use Illuminate\Queue\InteractsWithQueue;
|
||
|
|
use Illuminate\Queue\SerializesModels;
|
||
|
|
use Illuminate\Support\Facades\Redis;
|
||
|
|
|
||
|
|
class LoveGPTChat implements ShouldQueue
|
||
|
|
{
|
||
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||
|
|
use ResponseJson;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 类型
|
||
|
|
* @var
|
||
|
|
*/
|
||
|
|
protected $type;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 用户id
|
||
|
|
* @var
|
||
|
|
*/
|
||
|
|
protected $user_id;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 群聊id
|
||
|
|
* @var
|
||
|
|
*/
|
||
|
|
protected $team_id;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 小恋用户id
|
||
|
|
* @var
|
||
|
|
*/
|
||
|
|
protected $gpt_user_id;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 问题
|
||
|
|
* @var
|
||
|
|
*/
|
||
|
|
protected $question;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* gpt类型
|
||
|
|
* @var
|
||
|
|
*/
|
||
|
|
protected $gpt_type;
|
||
|
|
|
||
|
|
public function __construct($type, $user_id, $team_id, $gpt_user_id, $question, $gpt_type = null)
|
||
|
|
{
|
||
|
|
$this->type = $type;
|
||
|
|
$this->user_id = $user_id;
|
||
|
|
$this->team_id = $team_id;
|
||
|
|
$this->gpt_user_id = $gpt_user_id;
|
||
|
|
$this->question = $question;
|
||
|
|
$this->gpt_type = $gpt_type;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Execute the job.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
* @throws \GuzzleHttp\Exception\GuzzleException
|
||
|
|
*/
|
||
|
|
public function handle()
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
switch ($this->type){
|
||
|
|
case 'chat'://单聊
|
||
|
|
$this->handleChatToGPT();
|
||
|
|
break;
|
||
|
|
case 'group_chat'://群聊
|
||
|
|
$this->handleGroupChatToGPT();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}catch (\Exception $e){
|
||
|
|
$this->getError($e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private function handleGroupChatToGPT()
|
||
|
|
{
|
||
|
|
$session_id = "group_chat:user_id{$this->user_id}__to__team_id{$this->team_id}";
|
||
|
|
$config_model = UserGptConfig::where('user_id', $this->user_id)->value('model');
|
||
|
|
$cache_key = ApiRedisKey::getGroupChatGptReplyKey($this->team_id, $this->user_id);
|
||
|
|
$context_msg = Redis::get($cache_key);
|
||
|
|
|
||
|
|
$gpt_service = new LoveGPTService();
|
||
|
|
$res = $gpt_service->setQuestion($this->question)
|
||
|
|
->setSessionId($session_id)
|
||
|
|
->setModel($config_model)
|
||
|
|
->setContextMsg($context_msg)
|
||
|
|
->chat();
|
||
|
|
$code = $res['code'] ?? null;
|
||
|
|
$msg = $res['msg'] ?? null;
|
||
|
|
$data = $res['data'] ?? null;
|
||
|
|
if ($code != 0) {
|
||
|
|
throw new \Exception("love_gpt:群聊请求服务器错误_{$msg}");
|
||
|
|
}
|
||
|
|
//缓存对话上下文
|
||
|
|
$context_msg = $context_msg ? json_decode($context_msg, true) : [];
|
||
|
|
$context_msg_user = ['role' => 'user', 'content' => $this->question];
|
||
|
|
$context_msg_assistant = ['role' => 'assistant', 'content' => $data];
|
||
|
|
array_push($context_msg, $context_msg_user, $context_msg_assistant);
|
||
|
|
$context_msg = array_slice($context_msg, -6);
|
||
|
|
//缓存12小时
|
||
|
|
Redis::setex($cache_key, 60 * 60 * 12, json_encode($context_msg, JSON_UNESCAPED_UNICODE));
|
||
|
|
|
||
|
|
$nickname = UserTeam::where('team_id', $this->team_id)->where('user_id', $this->user_id)->value('nick');
|
||
|
|
if (!$nickname) {
|
||
|
|
$user = User::find($this->user_id);
|
||
|
|
$nickname = $user->nickname;
|
||
|
|
}
|
||
|
|
$msg = "@" . $nickname . "\n" . "[{$this->question}]" . "\n\n" . $data;
|
||
|
|
$im_service = new IMService(env('IM_APP_KEY'), env('IM_APP_SECRET'));
|
||
|
|
$option = [
|
||
|
|
'push' => true,
|
||
|
|
'route' => true
|
||
|
|
];
|
||
|
|
$im_service->sendMsg($this->gpt_user_id, 1, $this->team_id, 0, ['msg' => $msg], $option);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
private function handleChatToGPT()
|
||
|
|
{
|
||
|
|
$session_id = "love_chat:user_id{$this->user_id}";
|
||
|
|
$config_model = UserGptConfig::where('user_id', $this->user_id)->value('model');
|
||
|
|
$context_msg = [];
|
||
|
|
$history_msg = ChatMessage::whereIn('user_id', [$this->user_id, $this->gpt_user_id])
|
||
|
|
->whereIn('other_user_id', [$this->user_id, $this->gpt_user_id])
|
||
|
|
->orderBy('id', 'desc')
|
||
|
|
->limit(6)
|
||
|
|
->get();
|
||
|
|
foreach ($history_msg as $item) {
|
||
|
|
if ($item->user_id == $this->user_id) {
|
||
|
|
$context_msg[] = ['role' => 'user', 'content' => $item->content];
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
$context_msg[] = ['role' => 'assistant', 'content' => $item->content];
|
||
|
|
}
|
||
|
|
$context_msg = array_reverse($context_msg);//正序
|
||
|
|
$context_msg = json_encode($context_msg, JSON_UNESCAPED_UNICODE);
|
||
|
|
|
||
|
|
$gpt_service = new LoveGPTService();
|
||
|
|
$res = $gpt_service->setQuestion($this->question)
|
||
|
|
->setSessionId($session_id)
|
||
|
|
->setModel($config_model)
|
||
|
|
->setContextMsg($context_msg)
|
||
|
|
->setGptType($this->gpt_type)
|
||
|
|
->chat();
|
||
|
|
$code = $res['code'] ?? null;
|
||
|
|
$msg = $res['msg'] ?? null;
|
||
|
|
$data = $res['data'] ?? null;
|
||
|
|
if ($code != 0) {
|
||
|
|
throw new \Exception("love_gpt:单聊请求服务器错误_{$msg}");
|
||
|
|
}
|
||
|
|
$msg = $data;
|
||
|
|
$im_service = new IMService(env('IM_APP_KEY'), env('IM_APP_SECRET'));
|
||
|
|
$option = [
|
||
|
|
'push' => true,
|
||
|
|
'route' => true
|
||
|
|
];
|
||
|
|
$im_service->sendMsg($this->gpt_user_id, 0, $this->user_id, 0, ['msg' => $msg], $option);
|
||
|
|
}
|
||
|
|
}
|