From 89543f0df601b310a8feb4b74f742c3473478b76 Mon Sep 17 00:00:00 2001 From: geekr Date: Wed, 29 Mar 2023 13:32:45 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=8E=A5=E5=85=A5=E8=85=BE=E8=AE=AF?= =?UTF-8?q?=E4=BA=91=E5=86=85=E5=AE=B9=E8=BF=87=E6=BB=A4=E7=A1=AE=E4=BF=9D?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E5=90=88=E8=A7=84=E5=92=8C=E6=AD=A3=E5=BD=93?= =?UTF-8?q?=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Client/TmsService.php | 62 +++++++++++++++++ app/Facades/TmsFacade.php | 16 +++++ app/Http/Controllers/ChatController.php | 23 +++++-- app/Providers/RouteServiceProvider.php | 4 +- app/Providers/TmsServiceProvider.php | 34 ++++++++++ composer.json | 1 + composer.lock | 89 ++++++++++++++++++++++++- config/app.php | 2 +- config/tencent.php | 7 ++ public/index.php | 1 + resources/js/Pages/Chat.vue | 5 +- resources/js/store.js | 17 +++-- resources/views/app.blade.php | 16 ++++- 13 files changed, 262 insertions(+), 15 deletions(-) create mode 100644 app/Client/TmsService.php create mode 100644 app/Facades/TmsFacade.php create mode 100644 app/Providers/TmsServiceProvider.php create mode 100644 config/tencent.php diff --git a/app/Client/TmsService.php b/app/Client/TmsService.php new file mode 100644 index 0000000..4875888 --- /dev/null +++ b/app/Client/TmsService.php @@ -0,0 +1,62 @@ +endpoint = $endpoint; + $this->region = $region; + // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey + // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 + $this->credential = new Credential($secretId, $secretKey); + } + + public function checkText(string $content): bool | Exception + { + try { + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + $httpProfile = new HttpProfile(); + $httpProfile->setEndpoint($this->endpoint); + + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + $clientProfile = new ClientProfile(); + $clientProfile->setHttpProfile($httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + $client = new TmsClient($this->credential, $this->region, $clientProfile); + + // 实例化一个请求对象,每个接口都会对应一个request对象 + $req = new TextModerationRequest(); + + $params = [ + "Content" => base64_encode($content), + ]; + $req->fromJsonString(json_encode($params)); + + // 返回的resp是一个TextModerationResponse的实例,与请求对象对应 + $resp = $client->TextModeration($req); + if ($resp->Suggestion === 'Pass') { + return true; + } else { + return false; + } + } catch (TencentCloudSDKException $e) { + throw $e; + } + } +} diff --git a/app/Facades/TmsFacade.php b/app/Facades/TmsFacade.php new file mode 100644 index 0000000..cfc5bf0 --- /dev/null +++ b/app/Facades/TmsFacade.php @@ -0,0 +1,16 @@ + 'system', 'content' => 'You are GeekChat - A chatbot that can understand text, voice, draw image and translate. Answer as concisely as possible. Using Simplified Chinese as the first language.']; + private $preset = ['role' => 'system', 'content' => 'You are GeekChat - A ChatGPT clone. Answer as concisely as possible. Using Simplified Chinese as the first language.']; public function index() { @@ -39,6 +40,10 @@ public function chat(Request $request): JsonResponse 'regen' => ['required', 'in:true,false'], 'api_key' => 'sometimes|string', ]); + $passed = TmsFacade::checkText($request->input('prompt')); + if (!$passed) { + return response()->json(['message' => CONTENT_ERROR], 400); + } $regen = $request->boolean('regen'); $messages = $request->session()->get('messages', [$this->preset]); if ($regen && count($messages) == 1) { @@ -70,6 +75,10 @@ public function translate(Request $request): JsonResponse 'regen' => ['required', 'in:true,false'], 'api_key' => 'sometimes|string', ]); + $passed = TmsFacade::checkText($request->input('prompt')); + if (!$passed) { + return response()->json(['message' => CONTENT_ERROR], 400); + } $regen = $request->boolean('regen'); $messages = $request->session()->get('messages', [$this->preset]); if ($regen && count($messages) == 1) { @@ -170,14 +179,13 @@ public function audio(Request $request): JsonResponse ], 'api_key' => 'sometimes|string', ]); - // 保存到本地 $fileName = Str::uuid() . '.wav'; $dir = 'audios' . date('/Y/m/d', time()); $path = $request->audio->storeAs($dir, $fileName, 'local'); $messages = $request->session()->get('messages', [ - ['role' => 'system', 'content' => 'You are GeekChat - A chatbot that can understand text, voice, draw image and translate. Answer as concisely as possible. Make Mandarin Chinese the primary language'] + ['role' => 'system', 'content' => 'You are GeekChat - A ChatGPT clone. Answer as concisely as possible. Make Mandarin Chinese the primary language'] ]); // $path = 'audios/2023/03/09/test.wav';(测试用) // 调用 speech to text API 将语音转化为文字 @@ -199,7 +207,10 @@ public function audio(Request $request): JsonResponse } return response()->json(['message' => ['role' => 'assistant', 'content' => '对不起,我没有听清你说的话,请再试一次']]); } - + $passed = TmsFacade::checkText($result->text); + if (!$passed) { + return response()->json(['message' => CONTENT_ERROR], 400); + } // 接下来的流程和 ChatGPT 一样 $userMessage = ['role' => 'user', 'content' => $result->text]; $messages[] = $userMessage; @@ -216,6 +227,10 @@ public function image(Request $request): JsonResponse 'regen' => ['required', 'in:true,false'], 'api_key' => 'sometimes|string', ]); + $passed = TmsFacade::checkText($request->input('prompt')); + if (!$passed) { + return response()->json(['message' => CONTENT_ERROR], 400); + } $regen = $request->boolean('regen'); $messages = $request->session()->get('messages', [$this->preset]); if ($regen && count($messages) == 1) { diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 0d71900..2cc232d 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -47,12 +47,12 @@ protected function configureRateLimiting(): void RateLimiter::for('chat', function (Request $request) { return $request->input('api_key') ? Limit::none() - : Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); + : Limit::perMinute(600)->by($request->user()?->id ?: $request->ip()); }); RateLimiter::for('audio', function (Request $request) { return $request->input('api_key') ? Limit::none() - : Limit::perMinute(30)->by($request->user()?->id ?: $request->ip()); + : Limit::perMinute(300)->by($request->user()?->id ?: $request->ip()); }); RateLimiter::for('image', function (Request $request) { return $request->input('api_key') diff --git a/app/Providers/TmsServiceProvider.php b/app/Providers/TmsServiceProvider.php new file mode 100644 index 0000000..8d20126 --- /dev/null +++ b/app/Providers/TmsServiceProvider.php @@ -0,0 +1,34 @@ +app->singleton(TmsService::class, static function (): TmsService { + $secretId = config('tencent.secret_id'); + $secretKey = config('tencent.secret_key'); + $tmsEndpoint = config('tencent.tms_endpoint'); + $region = config('tencent.region'); + + return new TmsService($secretId, $secretKey, $tmsEndpoint, $region); + }); + + $this->app->alias(TmsService::class, 'tms'); + } + + /** + * Bootstrap services. + */ + public function boot(): void + { + // + } +} diff --git a/composer.json b/composer.json index 23ec65d..f104d25 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "orhanerday/open-ai": "^4.7", "spatie/laravel-responsecache": "^7.4", "spiral/roadrunner": "^2.8.2", + "tencentcloud/tms": "^3.0", "tightenco/ziggy": "^1.0" }, "require-dev": { diff --git a/composer.lock b/composer.lock index ff9ec7e..fdd80fb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4110333a8701670b1f8d0a5f5b597cf5", + "content-hash": "2d44e4edb81b503b49b81904515fe5b5", "packages": [ { "name": "brick/math", @@ -6588,6 +6588,93 @@ ], "time": "2023-02-16T09:57:23+00:00" }, + { + "name": "tencentcloud/common", + "version": "3.0.854", + "source": { + "type": "git", + "url": "https://github.com/tencentcloud-sdk-php/common.git", + "reference": "03c5b2892a3a9ef8deab0d133895c8fc0e51c64a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tencentcloud-sdk-php/common/zipball/03c5b2892a3a9ef8deab0d133895c8fc0e51c64a", + "reference": "03c5b2892a3a9ef8deab0d133895c8fc0e51c64a", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.3||^7.0", + "php": ">=5.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "TencentCloud\\": "./src/TencentCloud" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "tencentcloudapi", + "email": "tencentcloudapi@tencent.com", + "homepage": "https://cloud.tencent.com/document/sdk/PHP", + "role": "Developer" + } + ], + "description": "TencentCloudApi php sdk", + "homepage": "https://github.com/tencentcloud-sdk-php/common", + "support": { + "issues": "https://github.com/tencentcloud-sdk-php/common/issues", + "source": "https://github.com/tencentcloud-sdk-php/common/tree/3.0.854" + }, + "time": "2023-03-28T00:16:48+00:00" + }, + { + "name": "tencentcloud/tms", + "version": "3.0.854", + "source": { + "type": "git", + "url": "https://github.com/tencentcloud-sdk-php/tms.git", + "reference": "2d23dc83283cb6fe6cee9bc385a8b1879c536909" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tencentcloud-sdk-php/tms/zipball/2d23dc83283cb6fe6cee9bc385a8b1879c536909", + "reference": "2d23dc83283cb6fe6cee9bc385a8b1879c536909", + "shasum": "" + }, + "require": { + "tencentcloud/common": "3.0.854" + }, + "type": "library", + "autoload": { + "psr-4": { + "TencentCloud\\": "./src/TencentCloud" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "tencentcloudapi", + "email": "tencentcloudapi@tencent.com", + "homepage": "https://github.com/tencentcloud-sdk-php/tms", + "role": "Developer" + } + ], + "description": "TencentCloudApi php sdk tms", + "homepage": "https://github.com/tencentcloud-sdk-php/tms", + "support": { + "issues": "https://github.com/tencentcloud-sdk-php/tms/issues", + "source": "https://github.com/tencentcloud-sdk-php/tms/tree/3.0.854" + }, + "time": "2023-03-28T00:43:58+00:00" + }, { "name": "tightenco/ziggy", "version": "v1.5.0", diff --git a/config/app.php b/config/app.php index dc0ffa7..2706735 100644 --- a/config/app.php +++ b/config/app.php @@ -198,7 +198,7 @@ // App\Providers\BroadcastServiceProvider::class, \App\Providers\EventServiceProvider::class, \App\Providers\RouteServiceProvider::class, - + \App\Providers\TmsServiceProvider::class, ], /* diff --git a/config/tencent.php b/config/tencent.php new file mode 100644 index 0000000..4db68d9 --- /dev/null +++ b/config/tencent.php @@ -0,0 +1,7 @@ + env('TENCENT_SECRET_ID'), + 'secret_key' => env('TENCENT_SECRET_KEY'), + 'tms_endpoint' => env('TENCENT_TMS_ENDPOINT'), + 'region' => env('TENCENT_REGION'), +]; diff --git a/public/index.php b/public/index.php index 56f6d8d..31498af 100644 --- a/public/index.php +++ b/public/index.php @@ -5,6 +5,7 @@ define('LARAVEL_START', microtime(true)); define('SYSTEM_ERROR', '服务端出现异常,[请联系管理员](https://image.gstatics.cn/wechat.webp)。'); +define('CONTENT_ERROR', '内容不合规,请勿将本工具用于正常工作、学习、生活之外的无关场景'); /* diff --git a/resources/js/Pages/Chat.vue b/resources/js/Pages/Chat.vue index 9344851..eb85378 100644 --- a/resources/js/Pages/Chat.vue +++ b/resources/js/Pages/Chat.vue @@ -102,7 +102,7 @@ const regenerate = () => {