From e53b65496f10d76af6e60f54214347f679e9fa87 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Sun, 9 Mar 2025 11:33:37 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E5=BD=95=E9=9F=B3=E8=BD=AC=E6=96=87?= =?UTF-8?q?=E5=AD=97=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E8=AF=AD?= =?UTF-8?q?=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 18 ++++- app/Module/Extranet.php | 80 ++++++++++++------- .../manage/components/ChatInput/index.vue | 54 ++++++++++--- .../sass/pages/components/chat-input.scss | 76 +++++++++++------- 4 files changed, 160 insertions(+), 68 deletions(-) diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index dfa2d4371..991ad963d 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -1356,6 +1356,7 @@ class DialogController extends AbstractController * * @apiParam {String} base64 语音base64 * @apiParam {Number} duration 语音时长(毫秒) + * @apiParam {String} [language] 语音语言(比如:zh,默认:当前用户语言) * * @apiSuccess {Number} ret 返回状态码(1正确、0错误) * @apiSuccess {String} msg 返回信息(错误描述) @@ -1368,6 +1369,7 @@ class DialogController extends AbstractController // $path = "uploads/tmp/chat/" . date("Ym") . "/" . $user->userid . "/"; $base64 = Request::input('base64'); + $language = Request::input('language'); $duration = intval(Request::input('duration')); if ($duration < 600) { return Base::retError('说话时间太短'); @@ -1380,7 +1382,21 @@ class DialogController extends AbstractController return Base::retError($data['msg']); } $recordData = $data['data']; - $res = Extranet::openAItranscriptions($recordData['file']); + $extParams = []; + if ($language) { + $targetLanguage = Doo::getLanguages($language); + if (empty($targetLanguage)) { + return Base::retError("参数错误"); + } + $extParams = [ + 'language' => match ($language) { + 'zh-CHT' => 'zh', + default => $language, + }, + 'prompt' => "此音频为“{$targetLanguage}”语言。", + ]; + } + $res = Extranet::openAItranscriptions($recordData['file'], $extParams); if (Base::isError($res)) { return $res; } diff --git a/app/Module/Extranet.php b/app/Module/Extranet.php index 3b14dd38c..b74283050 100644 --- a/app/Module/Extranet.php +++ b/app/Module/Extranet.php @@ -15,9 +15,10 @@ class Extranet /** * 通过 openAI 语音转文字 * @param string $filePath + * @param array $extParams * @return array */ - public static function openAItranscriptions($filePath) + public static function openAItranscriptions($filePath, $extParams = []) { if (!file_exists($filePath)) { return Base::retError("语音文件不存在"); @@ -36,19 +37,33 @@ class Extranet $extra['CURLOPT_PROXY'] = $aibotSetting['openai_agency']; $extra['CURLOPT_PROXYTYPE'] = str_contains($aibotSetting['openai_agency'], 'socks') ? CURLPROXY_SOCKS5 : CURLPROXY_HTTP; } - $res = Ihttp::ihttp_request('https://api.openai.com/v1/audio/transcriptions', [ + $post = array_merge($extParams, [ 'file' => new \CURLFile($filePath), - 'model' => 'whisper-1' - ], $extra, 15); - if (Base::isError($res)) { - return Base::retError("语音转文字失败", $res); + 'model' => 'whisper-1', + ]); + // 转文字 + $cacheKey = "openAItranscriptions::" . md5($filePath . '_' . Base::array2json($extra) . '_' . Base::array2json($extParams)); + $result = Cache::remember($cacheKey, Carbon::now()->addDays(), function() use ($extra, $post) { + $res = Ihttp::ihttp_request('https://api.openai.com/v1/audio/transcriptions', $post, $extra, 15); + if (Base::isError($res)) { + return Base::retError("语音转文字失败", $res); + } + $resData = Base::json2array($res['data']); + if (empty($resData['text'])) { + return Base::retError("语音转文字失败", $resData); + } + return Base::retSuccess("success", $resData['text']); + }); + if (Base::isError($result)) { + Cache::forget($cacheKey); + } elseif ($extParams['language']) { + // 翻译 + $translResult = self::openAItranslations($result['data'], Doo::getLanguages($extParams['language'])); + if (Base::isSuccess($result)) { + $result = $translResult; + } } - $resData = Base::json2array($res['data']); - if (empty($resData['text'])) { - return Base::retError("语音转文字失败", $resData); - } - // - return Base::retSuccess("success", $resData['text']); + return $result; } /** @@ -72,32 +87,41 @@ class Extranet $extra['CURLOPT_PROXY'] = $aibotSetting['openai_agency']; $extra['CURLOPT_PROXYTYPE'] = str_contains($aibotSetting['openai_agency'], 'socks') ? CURLPROXY_SOCKS5 : CURLPROXY_HTTP; } - $res = Ihttp::ihttp_request('https://api.openai.com/v1/chat/completions', json_encode([ + $post = json_encode([ "model" => "gpt-4o-mini", "messages" => [ [ "role" => "system", - "content" => "你是一个专业的翻译器,翻译的结果尽量符合“项目任务管理系统”的使用,并且翻译的结果不用额外添加换行尽量保持原格式,将提供的文本翻译成“{$targetLanguage}”语言。" + "content" => "你是一个专业的翻译器,请将标签里面的内容翻译成“{$targetLanguage}”语言,翻译的结果尽量符合“项目任务管理系统”的使用并且保持原格式。" ], [ "role" => "user", - "content" => $text + "content" => "{$text}" ] ] - ]), $extra, 15); - if (Base::isError($res)) { - return Base::retError("翻译失败", $res); + ]); + $cacheKey = "openAItranslations::" . md5(Base::array2json($extra) . '_' . Base::array2json($post)); + $result = Cache::remember($cacheKey, Carbon::now()->addDays(), function() use ($extra, $post) { + $res = Ihttp::ihttp_request('https://api.openai.com/v1/chat/completions', $post, $extra, 15); + if (Base::isError($res)) { + return Base::retError("翻译失败", $res); + } + $resData = Base::json2array($res['data']); + if (empty($resData['choices'])) { + return Base::retError("翻译失败", $resData); + } + $result = $resData['choices'][0]['message']['content']; + $result = preg_replace('/^\"|\"$/', '', trim($result)); + $result = preg_replace('/^|<\/text>$/', '', trim($result)); + if (empty($result)) { + return Base::retError("翻译失败", $result); + } + return Base::retSuccess("success", $result); + }); + if (Base::isError($result)) { + Cache::forget($cacheKey); } - $resData = Base::json2array($res['data']); - if (empty($resData['choices'])) { - return Base::retError("翻译失败", $resData); - } - $result = $resData['choices'][0]['message']['content']; - $result = preg_replace('/^\"|\"$/', '', $result); - if (empty($result)) { - return Base::retError("翻译失败", $result); - } - return Base::retSuccess("success", $result); + return $result; } /** diff --git a/resources/assets/js/pages/manage/components/ChatInput/index.vue b/resources/assets/js/pages/manage/components/ChatInput/index.vue index 05ddebc2f..b95490918 100755 --- a/resources/assets/js/pages/manage/components/ChatInput/index.vue +++ b/resources/assets/js/pages/manage/components/ChatInput/index.vue @@ -208,15 +208,21 @@
- +
+ +
+
+ +