From 4b89eb88bd6258e152d30dcccb1da06efabce5e3 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Fri, 6 Dec 2024 14:44:59 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96AI=E7=BE=A4=E8=81=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/SystemController.php | 44 +----- app/Models/WebSocketDialogMsg.php | 9 ++ app/Tasks/BotReceiveMsgTask.php | 148 ++++++++++++++---- app/Tasks/WebSocketDialogMsgTask.php | 2 +- 4 files changed, 130 insertions(+), 73 deletions(-) diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index e48815d05..a49da5fd7 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -289,7 +289,7 @@ class SystemController extends AbstractController */ public function setting__aibot() { - $user = User::auth('admin'); + User::auth('admin'); // $type = trim(Request::input('type')); $setting = Base::setting('aibotSetting'); @@ -298,7 +298,6 @@ class SystemController extends AbstractController return Base::retError('当前环境禁止修改'); } Base::checkClientVersion('0.41.11'); - $backup = $setting; $all = Request::input(); foreach ($all as $key => $value) { if (isset($setting[$key])) { @@ -306,47 +305,6 @@ class SystemController extends AbstractController } } $setting = Base::setting('aibotSetting', Base::newTrim($setting)); - $tempMsg = [ - 'type' => 'content', - 'content' => '设置成功' - ]; - // - if ($backup['openai_key'] != $setting['openai_key']) { - $botUser = User::botGetOrCreate('ai-openai'); - if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { - WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', $tempMsg, $botUser->userid, true, false, true); - } - } - if ($backup['claude_key'] != $setting['claude_key']) { - $botUser = User::botGetOrCreate('ai-claude'); - if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { - WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', $tempMsg, $botUser->userid, true, false, true); - } - } - if ($backup['wenxin_key'] != $setting['wenxin_key']) { - $botUser = User::botGetOrCreate('ai-wenxin'); - if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { - WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', $tempMsg, $botUser->userid, true, false, true); - } - } - if ($backup['qianwen_key'] != $setting['qianwen_key']) { - $botUser = User::botGetOrCreate('ai-qianwen'); - if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { - WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', $tempMsg, $botUser->userid, true, false, true); - } - } - if ($backup['gemini_key'] != $setting['gemini_key']) { - $botUser = User::botGetOrCreate('ai-gemini'); - if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { - WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', $tempMsg, $botUser->userid, true, false, true); - } - } - if ($backup['zhipu_key'] != $setting['zhipu_key']) { - $botUser = User::botGetOrCreate('ai-zhipu'); - if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { - WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', $tempMsg, $botUser->userid, true, false, true); - } - } } // if (env("SYSTEM_SETTING") == 'disabled') { diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php index 45db4e556..72362a42b 100644 --- a/app/Models/WebSocketDialogMsg.php +++ b/app/Models/WebSocketDialogMsg.php @@ -39,6 +39,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property \Illuminate\Support\Carbon|null $deleted_at * @property-read int|mixed $percentage * @property-read \App\Models\WebSocketDialog|null $webSocketDialog + * @property-read \App\Models\User|null $user * @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend() * @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden() * @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array) @@ -96,6 +97,14 @@ class WebSocketDialogMsg extends AbstractModel return $this->hasOne(WebSocketDialog::class, 'id', 'dialog_id'); } + /** + * @return \Illuminate\Database\Eloquent\Relations\HasOne + */ + public function user(): \Illuminate\Database\Eloquent\Relations\HasOne + { + return $this->hasOne(User::class, 'userid', 'userid'); + } + /** * 阅读占比 * @return int|mixed diff --git a/app/Tasks/BotReceiveMsgTask.php b/app/Tasks/BotReceiveMsgTask.php index f1ea5b89c..0be9ae407 100644 --- a/app/Tasks/BotReceiveMsgTask.php +++ b/app/Tasks/BotReceiveMsgTask.php @@ -2,6 +2,8 @@ namespace App\Tasks; +use App\Models\Project; +use App\Models\ProjectTask; use App\Models\User; use App\Models\UserBot; use App\Models\WebSocketDialog; @@ -12,6 +14,7 @@ use App\Module\Doo; use App\Module\Ihttp; use Carbon\Carbon; use DB; +use League\HTMLToMarkdown\HtmlConverter; @error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); @@ -23,17 +26,19 @@ use DB; */ class BotReceiveMsgTask extends AbstractTask { - protected $userid; - protected $msgId; - protected $mention; - protected $client = []; + protected $userid; // 机器人ID + protected $msgId; // 消息ID + protected $mention; // 是否提及 + protected $mentionOther; // 是否提及其他人 + protected $client = []; // 客户端信息(版本、语言、平台) - public function __construct($userid, $msgId, $mention, $client = []) + public function __construct($userid, $msgId, $mentions, $client = []) { parent::__construct(...func_get_args()); $this->userid = $userid; $this->msgId = $msgId; - $this->mention = $mention; + $this->mention = array_intersect([$userid], $mentions) ? 1 : 0; // 是否提及(不含@所有人) + $this->mentionOther = array_diff($mentions, [0, $userid]) ? 1 : 0; // 是否提及其他人 $this->client = is_array($client) ? $client : []; } @@ -43,12 +48,14 @@ class BotReceiveMsgTask extends AbstractTask if (empty($botUser)) { return; } - $msg = WebSocketDialogMsg::find($this->msgId); + $msg = WebSocketDialogMsg::with(['user'])->find($this->msgId); if (empty($msg)) { return; } $msg->readSuccess($botUser->userid); - $this->botManagerReceive($msg, $botUser); + if (!$msg->user?->bot) { + $this->botReceiveBusiness($msg, $botUser); + } } public function end() @@ -57,12 +64,12 @@ class BotReceiveMsgTask extends AbstractTask } /** - * 机器人管理处理消息 + * 机器人处理消息 * @param WebSocketDialogMsg $msg * @param User $botUser * @return void */ - private function botManagerReceive(WebSocketDialogMsg $msg, User $botUser) + private function botReceiveBusiness(WebSocketDialogMsg $msg, User $botUser) { // 位置消息(仅支持签到机器人) if ($msg->type === 'location') { @@ -90,8 +97,13 @@ class BotReceiveMsgTask extends AbstractTask return; } + // 如果是群聊,未提及丹提及其他人 + if ($dialog->type === 'group' && !$this->mention && $this->mentionOther) { + return; + } + // 推送Webhook - $this->botManagerWebhook($command, $msg, $botUser, $dialog); + $this->botWebhookBusiness($command, $msg, $botUser, $dialog); // 仅支持用户会话 if ($dialog->type !== 'user') { @@ -173,7 +185,7 @@ class BotReceiveMsgTask extends AbstractTask case '/hello': case '/info': $botId = $isManager ? $array[1] : $botUser->userid; - $data = $this->botManagerOne($botId, $msg->userid); + $data = $this->botOne($botId, $msg->userid); if (!$data) { $content = "机器人不存在。"; } @@ -222,7 +234,7 @@ class BotReceiveMsgTask extends AbstractTask $content = "机器人名称由2-20个字符组成。"; break; } - $data = $this->botManagerOne($botId, $msg->userid); + $data = $this->botOne($botId, $msg->userid); if ($data) { $data->nickname = $nameString; $data->az = Base::getFirstCharter($nameString); @@ -239,7 +251,7 @@ class BotReceiveMsgTask extends AbstractTask */ case '/deletebot': $botId = $isManager ? $array[1] : $botUser->userid; - $data = $this->botManagerOne($botId, $msg->userid); + $data = $this->botOne($botId, $msg->userid); if ($data) { $data->deleteUser('delete bot'); } else { @@ -252,7 +264,7 @@ class BotReceiveMsgTask extends AbstractTask */ case '/token': $botId = $isManager ? $array[1] : $botUser->userid; - $data = $this->botManagerOne($botId, $msg->userid); + $data = $this->botOne($botId, $msg->userid); if ($data) { User::generateToken($data); } else { @@ -265,7 +277,7 @@ class BotReceiveMsgTask extends AbstractTask */ case '/revoke': $botId = $isManager ? $array[1] : $botUser->userid; - $data = $this->botManagerOne($botId, $msg->userid); + $data = $this->botOne($botId, $msg->userid); if ($data) { $data->encrypt = Base::generatePassword(6); $data->password = Doo::md5s(Base::generatePassword(32), $data->encrypt); @@ -281,7 +293,7 @@ class BotReceiveMsgTask extends AbstractTask case '/clearday': $botId = $isManager ? $array[1] : $botUser->userid; $clearDay = $isManager ? $array[2] : $array[1]; - $data = $this->botManagerOne($botId, $msg->userid); + $data = $this->botOne($botId, $msg->userid); if ($data) { $userBot = UserBot::whereBotId($botId)->whereUserid($msg->userid)->first(); if ($userBot) { @@ -302,7 +314,7 @@ class BotReceiveMsgTask extends AbstractTask case '/webhook': $botId = $isManager ? $array[1] : $botUser->userid; $webhookUrl = $isManager ? $array[2] : $array[1]; - $data = $this->botManagerOne($botId, $msg->userid); + $data = $this->botOne($botId, $msg->userid); if (strlen($webhookUrl) > 255) { $content = "webhook地址最长仅支持255个字符。"; } elseif ($data) { @@ -325,7 +337,7 @@ class BotReceiveMsgTask extends AbstractTask case '/dialog': $botId = $isManager ? $array[1] : $botUser->userid; $nameKey = $isManager ? $array[2] : $array[1]; - $data = $this->botManagerOne($botId, $msg->userid); + $data = $this->botOne($botId, $msg->userid); if ($data) { $list = DB::table('web_socket_dialog_users as u') ->select(['d.*', 'u.top_at', 'u.last_at', 'u.mark_unread', 'u.silence', 'u.hide', 'u.color', 'u.updated_at as user_at']) @@ -397,7 +409,7 @@ class BotReceiveMsgTask extends AbstractTask * @param WebSocketDialog $dialog * @return void */ - private function botManagerWebhook(string $command, WebSocketDialogMsg $msg, User $botUser, WebSocketDialog $dialog) + private function botWebhookBusiness(string $command, WebSocketDialogMsg $msg, User $botUser, WebSocketDialog $dialog) { $serverUrl = 'http://' . env('APP_IPPR') . '.3'; $userBot = null; @@ -427,14 +439,6 @@ class BotReceiveMsgTask extends AbstractTask if (in_array($this->client['platform'], ['win', 'mac', 'web']) && !Base::judgeClientVersion("0.41.11", $this->client['version'])) { $errorContent = '当前客户端版本低(所需版本≥v0.41.11)。'; } - $aiPrompt = WebSocketDialogConfig::where([ - 'dialog_id' => $dialog->id, - 'userid' => $msg->userid, - 'type' => 'ai_prompt', - ])->value('value'); - if ($aiPrompt) { - $extras['system_message'] = $aiPrompt; - } if ($msg->reply_id > 0) { $replyMsg = WebSocketDialogMsg::find($msg->reply_id); $replyCommand = ''; @@ -446,6 +450,7 @@ class BotReceiveMsgTask extends AbstractTask } $command = $replyCommand . $command; } + $this->AIGenerateSystemMessageOrBeforeText($msg->userid, $dialog, $extras); $webhookUrl = "{$serverUrl}/ai/chat"; } else { // 用户机器人 @@ -498,11 +503,12 @@ class BotReceiveMsgTask extends AbstractTask } /** + * 获取机器人信息 * @param $botId * @param $userid * @return User */ - private function botManagerOne($botId, $userid) + private function botOne($botId, $userid) { $botId = intval($botId); $userid = intval($userid); @@ -551,4 +557,88 @@ class BotReceiveMsgTask extends AbstractTask } return $command; } + + /** + * 生成AI系统提示词或前置消息 + * @param int|null $userid + * @param WebSocketDialog $dialog + * @param array $extras + * @return void + */ + private function AIGenerateSystemMessageOrBeforeText(int|null $userid, WebSocketDialog $dialog, array &$extras) + { + $system_message = null; + $before_text = []; + switch ($dialog->type) { + case "user": + $aiPrompt = WebSocketDialogConfig::where([ + 'dialog_id' => $dialog->id, + 'userid' => $userid, + 'type' => 'ai_prompt', + ])->value('value'); + if ($aiPrompt) { + $system_message = $aiPrompt; + } + break; + case "group": + switch ($dialog->group_type) { + case 'user': + break; + case 'project': + $projectInfo = Project::select(['id', 'name', 'archived_at', 'deleted_at'])->whereDialogId($dialog->id)->first(); + if ($projectInfo) { + $before_text[] = "当前我在项目【{$projectInfo->name}】中"; + if ($projectInfo->desc) { + $before_text[] = "项目描述:{$projectInfo->desc}"; + } + $before_text[] = <<select(['id', 'name', 'complete_at', 'archived_at', 'deleted_at'])->whereDialogId($dialog->id)->first(); + if ($taskInfo) { + $before_text[] = "当前我在任务【{$taskInfo->name}】中"; + if ($taskInfo->content) { + $taskDesc = $taskInfo->content?->getContentInfo(); + if ($taskDesc) { + $converter = new HtmlConverter(['strip_tags' => true]); + $before_text[] = <<convert($taskDesc['content'])} + ``` + EOF; + } + } + $before_text[] = <<whereBot(1)->first(); if ($botUser) { - $this->endArray[] = new BotReceiveMsgTask($botUser->userid, $msg->id, $mention, $this->client); + $this->endArray[] = new BotReceiveMsgTask($botUser->userid, $msg->id, $mentions, $this->client); } } }