From 569145196edcdc49c4751a30bbd8cb7cc82f0908 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Thu, 27 Jul 2023 16:00:16 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=B7=BB=E5=8A=A0ChatGPT=E3=80=81Claud?= =?UTF-8?q?e=E6=99=BA=E8=83=BD=E6=9C=BA=E5=99=A8=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 2 +- app/Http/Controllers/Api/SystemController.php | 68 ++++++++++++++ app/Models/User.php | 10 ++ app/Tasks/BotReceiveMsgTask.php | 87 ++++++++++++++---- ...2023_07_27_145646_create_default_robot.php | 30 ++++++ docker-compose.yml | 3 +- docker/ai/.gitignore | 1 + docker/ai/ai.conf | 10 ++ docker/nginx/default.conf | 9 ++ public/images/avatar/default_claude.png | Bin 0 -> 6199 bytes public/images/avatar/default_openai.png | Bin 0 -> 6671 bytes .../manage/setting/components/SystemAibot.vue | 83 +++++++++++++++++ .../assets/js/pages/manage/setting/system.vue | 5 + .../public/images/avatar/default_claude.png | Bin 0 -> 6199 bytes .../public/images/avatar/default_openai.png | Bin 0 -> 6671 bytes 15 files changed, 290 insertions(+), 18 deletions(-) create mode 100644 database/migrations/2023_07_27_145646_create_default_robot.php create mode 100644 docker/ai/.gitignore create mode 100644 docker/ai/ai.conf create mode 100644 public/images/avatar/default_claude.png create mode 100644 public/images/avatar/default_openai.png create mode 100644 resources/assets/js/pages/manage/setting/components/SystemAibot.vue create mode 100644 resources/assets/statics/public/images/avatar/default_claude.png create mode 100644 resources/assets/statics/public/images/avatar/default_openai.png diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 99258413a..14287de11 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -658,7 +658,7 @@ class DialogController extends AbstractController $userid = intval(Request::input('userid')); $stream_url = trim(Request::input('stream_url')); // - if ($userid < 1 || !str_starts_with($stream_url, 'http')) { + if ($userid <= 0) { return Base::retError('参数错误'); } // diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index 4470c6a80..7327e10c7 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers\Api; +use App\Models\WebSocketDialog; +use App\Models\WebSocketDialogMsg; use Request; use Session; use Response; @@ -228,6 +230,72 @@ class SystemController extends AbstractController return Base::retSuccess('success', $setting ?: json_decode('{}')); } + /** + * @api {get} api/system/setting/aibot 03. 获取会议设置、保存AI机器人设置(限管理员) + * + * @apiVersion 1.0.0 + * @apiGroup system + * @apiName setting__aibot + * + * @apiParam {String} type + * - get: 获取(默认) + * - save: 保存设置(参数:['openai_key', 'openai_agency', 'claude_token', 'claude_agency']) + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function setting__aibot() + { + $user = User::auth('admin'); + // + $type = trim(Request::input('type')); + $setting = Base::setting('aibotSetting'); + if ($type == 'save') { + if (env("SYSTEM_SETTING") == 'disabled') { + return Base::retError('当前环境禁止修改'); + } + $all = Request::input(); + foreach ($all as $key => $value) { + if (!in_array($key, [ + 'openai_key', + 'openai_agency', + 'claude_token', + 'claude_agency', + ])) { + unset($all[$key]); + } + } + $backup = $setting; + $setting = Base::setting('aibotSetting', Base::newTrim($all)); + // + 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, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true); + } + } + if ($backup['claude_token'] != $setting['claude_token']) { + $botUser = User::botGetOrCreate('ai-claude'); + if ($botUser && $dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) { + WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => "设置成功"], $botUser->userid, true, false, true); + } + } + } + // + if (env("SYSTEM_SETTING") == 'disabled') { + foreach ([ + 'openai_key', + 'openai_agency', + 'claude_token', + 'claude_agency', + ] as $item) { + $setting[$item] = substr($setting[$item], 0, 4) . str_repeat('*', strlen($setting[$item]) - 8) . substr($setting[$item], -4); + } + } + // + return Base::retSuccess('success', $setting ?: json_decode('{}')); + } + /** * @api {get} api/system/setting/checkin 04. 获取签到设置、保存签到设置(限管理员) * diff --git a/app/Models/User.php b/app/Models/User.php index d254c1efb..886ac424c 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -533,6 +533,10 @@ class User extends AbstractModel return url("images/avatar/default_anon.png"); case 'approval-alert@bot.system': return url("images/avatar/default_approval.png"); + case 'ai-openai@bot.system': + return url("images/avatar/default_openai.png"); + case 'ai-claude@bot.system': + return url("images/avatar/default_claude.png"); case 'bot-manager@bot.system': return url("images/avatar/default_bot.png"); } @@ -619,6 +623,12 @@ class User extends AbstractModel case 'approval-alert': $update['nickname'] = '审批'; break; + case 'ai-openai': + $update['nickname'] = 'ChatGPT'; + break; + case 'ai-claude': + $update['nickname'] = 'Claude'; + break; case 'bot-manager': $update['nickname'] = '机器人管理'; break; diff --git a/app/Tasks/BotReceiveMsgTask.php b/app/Tasks/BotReceiveMsgTask.php index fb0fa81c6..92fb072c5 100644 --- a/app/Tasks/BotReceiveMsgTask.php +++ b/app/Tasks/BotReceiveMsgTask.php @@ -81,22 +81,7 @@ class BotReceiveMsgTask extends AbstractTask if ($command && !str_starts_with($command, '/') && ($dialog->type === 'user' || $this->mention)) { - $userBot = UserBot::whereBotId($botUser->userid)->first(); - if ($userBot && preg_match("/^https*:\/\//", $userBot->webhook_url)) { - Ihttp::ihttp_post($userBot->webhook_url, [ - 'text' => $command, - 'token' => User::generateToken($botUser), - 'dialog_id' => $dialog->id, - 'dialog_type' => $dialog->type, - 'msg_id' => $msg->id, - 'msg_uid' => $msg->userid, - 'mention' => $this->mention ? 1 : 0, - 'bot_uid' => $botUser->userid, - 'version' => Base::getVersion(), - ], 10); - $userBot->webhook_num++; - $userBot->save(); - } + $this->botManagerWebhook($command, $msg, $botUser, $dialog); } if ($dialog->type !== 'user') { return; @@ -366,6 +351,76 @@ class BotReceiveMsgTask extends AbstractTask } } + /** + * 机器人处理 Webhook + * @param string $command + * @param WebSocketDialogMsg $msg + * @param User $botUser + * @param WebSocketDialog $dialog + * @return void + */ + private function botManagerWebhook(string $command, WebSocketDialogMsg $msg, User $botUser, WebSocketDialog $dialog) + { + $serverUrl = 'http://' . env('APP_IPPR') . '.3'; + $userBot = null; + $extras = []; + switch ($botUser->email) { + // ChatGPT 机器人 + case 'ai-openai@bot.system': + $setting = Base::setting('aibotSetting'); + $webhookUrl = "{$serverUrl}/ai/openai/send"; + $extras = [ + 'openai_key' => $setting['openai_key'], + 'openai_agency' => $setting['openai_agency'], + 'server_url' => $serverUrl, + ]; + if (empty($extras['openai_key'])) { + WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', ['text' => 'Robot disabled'], $botUser->userid, false, false, true); // todo 未能在任务end事件来发送任务 + return; + } + break; + // Claude 机器人 + case 'ai-claude@bot.system': + $setting = Base::setting('aibotSetting'); + $webhookUrl = "{$serverUrl}/ai/claude/send"; + $extras = [ + 'claude_token' => $setting['claude_token'], + 'claude_agency' => $setting['claude_agency'], + 'server_url' => $serverUrl, + ]; + if (empty($extras['claude_token'])) { + WebSocketDialogMsg::sendMsg(null, $msg->dialog_id, 'text', ['text' => 'Robot disabled'], $botUser->userid, false, false, true); // todo 未能在任务end事件来发送任务 + return; + } + break; + // 其他机器人 + default: + $userBot = UserBot::whereBotId($botUser->userid)->first(); + $webhookUrl = $userBot?->webhook_url; + break; + } + if (!preg_match("/^https*:\/\//", $webhookUrl)) { + return; + } + // + Ihttp::ihttp_post($webhookUrl, [ + 'text' => $command, + 'token' => User::generateToken($botUser), + 'dialog_id' => $dialog->id, + 'dialog_type' => $dialog->type, + 'msg_id' => $msg->id, + 'msg_uid' => $msg->userid, + 'mention' => $this->mention ? 1 : 0, + 'bot_uid' => $botUser->userid, + 'version' => Base::getVersion(), + 'extras' => Base::array2json($extras) + ], 10); + if ($userBot) { + $userBot->webhook_num++; + $userBot->save(); + } + } + /** * @param $botId * @param $userid diff --git a/database/migrations/2023_07_27_145646_create_default_robot.php b/database/migrations/2023_07_27_145646_create_default_robot.php new file mode 100644 index 000000000..c8936c84a --- /dev/null +++ b/database/migrations/2023_07_27_145646_create_default_robot.php @@ -0,0 +1,30 @@ ++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 +
+
+
+

{{ $L('ChatGTP') }}

+
+ + + + + + +
+
+
+

{{ $L('Claude') }}

+
+ + + + + + +
+
+
+ +
+ + + diff --git a/resources/assets/js/pages/manage/setting/system.vue b/resources/assets/js/pages/manage/setting/system.vue index 2b9eaac86..69da1982a 100644 --- a/resources/assets/js/pages/manage/setting/system.vue +++ b/resources/assets/js/pages/manage/setting/system.vue @@ -10,6 +10,9 @@ + + + @@ -38,9 +41,11 @@ import SystemAppPush from "./components/SystemAppPush"; import SystemMeeting from "./components/SystemMeeting"; import SystemCheckin from "./components/SystemCheckin"; import SystemThirdAccess from "./components/SystemThirdAccess"; +import SystemAibot from "./components/SystemAibot.vue"; export default { components: { + SystemAibot, SystemThirdAccess, SystemCheckin, SystemMeeting, diff --git a/resources/assets/statics/public/images/avatar/default_claude.png b/resources/assets/statics/public/images/avatar/default_claude.png new file mode 100644 index 0000000000000000000000000000000000000000..8c9cdc538f64ae0470aa54894402a032bf897207 GIT binary patch literal 6199 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