From 8ed9186ff415531dec26b0366f7f8b93bce838fa Mon Sep 17 00:00:00 2001 From: kuaifan Date: Fri, 14 Feb 2025 00:50:45 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20AI=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=A8=A1=E5=9E=8B=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Models/Setting.php | 142 ++++++++++++++++-- app/Models/UserBot.php | 11 +- .../pages/manage/components/DialogWrapper.vue | 20 +-- .../manage/setting/components/SystemAibot.vue | 125 +++++++++------ resources/assets/js/store/utils.js | 93 ------------ 5 files changed, 227 insertions(+), 164 deletions(-) diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 5897ca6cf..0da909f4b 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -66,24 +66,33 @@ class Setting extends AbstractModel } $array = []; $aiList = ['openai', 'claude', 'deepseek', 'gemini', 'zhipu', 'qianwen', 'wenxin']; - $fieldList = ['key', 'model', 'base_url', 'agency', 'temperature', 'system', 'secret']; + $fieldList = ['key', 'models', 'model', 'base_url', 'agency', 'temperature', 'system', 'secret']; foreach ($aiList as $aiName) { foreach ($fieldList as $fieldName) { $key = $aiName . '_' . $fieldName; - if ($fieldName == 'temperature' && $value[$key]) { - $array[$key] = floatval(min(1, max(0, floatval($value[$key]) ?: 0.7))); - continue; + $content = $value[$key] ? trim($value[$key]) : ''; + switch ($fieldName) { + case 'models': + if ($content) { + $content = explode("\n", $content); + $content = array_filter($content); + } + if (empty($content)) { + $content = self::AIDefaultModels($aiName); + } + $content = implode("\n", $content); + break; + case 'model': + $models = Setting::AIModels2Array($array[$key . 's'], true); + $content = in_array($content, $models) ? $content : ($models[0] ?? ''); + break; + case 'temperature': + if ($content) { + $content = floatval(min(1, max(0, floatval($content) ?: 0.7))); + } + break; } - $array[$key] = $value[$key] ?: match ($key) { - 'openai_model' => 'gpt-4o-mini', - 'claude_model' => 'claude-3-5-sonnet-latest', - 'deepseek_model' => 'deepseek-chat', - 'gemini_model' => 'gemini-1.5-flash', - 'zhipu_model' => 'glm-4', - 'qianwen_model' => 'qwen-turbo', - 'wenxin_model' => 'ernie-4.0-8k', - default => '', - }; + $array[$key] = $content; } } $value = $array; @@ -103,6 +112,111 @@ class Setting extends AbstractModel return !!$array[$ai . '_key']; } + /** + * AI默认模型 + * @param string $ai + * @return array + */ + public static function AIDefaultModels($ai = 'openai') + { + return match ($ai) { + 'openai' => [ + 'gpt-4: GPT-4', + 'gpt-4-turbo: GPT-4 Turbo', + 'gpt-4o: GPT-4o', + 'gpt-4o-mini: GPT-4o Mini', + 'o1: GPT-o1', + 'o1-mini: GPT-o1 Mini', + 'o3-mini: GPT-o3 Mini', + 'gpt-3.5-turbo: GPT-3.5 Turbo', + 'gpt-3.5-turbo-16k: GPT-3.5 Turbo 16K', + 'gpt-3.5-turbo-0125: GPT-3.5 Turbo 0125', + 'gpt-3.5-turbo-1106: GPT-3.5 Turbo 1106' + ], + 'claude' => [ + 'claude-3-5-sonnet-latest: Claude 3.5 Sonnet', + 'claude-3-5-sonnet-20241022: Claude 3.5 Sonnet 20241022', + 'claude-3-5-haiku-latest: Claude 3.5 Haiku', + 'claude-3-5-haiku-20241022: Claude 3.5 Haiku 20241022', + 'claude-3-opus-latest: Claude 3 Opus', + 'claude-3-opus-20240229: Claude 3 Opus 20240229', + 'claude-3-haiku-20240307: Claude 3 Haiku 20240307', + 'claude-2.1: Claude 2.1', + 'claude-2.0: Claude 2.0' + ], + 'deepseek' => [ + 'deepseek-chat: DeepSeek V3', + 'deepseek-reasoner: DeepSeek R1' + ], + 'wenxin' => [ + 'ernie-4.0-8k: Ernie 4.0 8K', + 'ernie-4.0-8k-latest: Ernie 4.0 8K Latest', + 'ernie-4.0-turbo-128k: Ernie 4.0 Turbo 128K', + 'ernie-4.0-turbo-8k: Ernie 4.0 Turbo 8K', + 'ernie-3.5-128k: Ernie 3.5 128K', + 'ernie-3.5-8k: Ernie 3.5 8K', + 'ernie-speed-128k: Ernie Speed 128K', + 'ernie-speed-8k: Ernie Speed 8K', + 'ernie-lite-8k: Ernie Lite 8K', + 'ernie-tiny-8k: Ernie Tiny 8K' + ], + 'qianwen' => [ + 'qwen-max: QWEN Max', + 'qwen-max-latest: QWEN Max Latest', + 'qwen-turbo: QWEN Turbo', + 'qwen-turbo-latest: QWEN Turbo Latest', + 'qwen-plus: QWEN Plus', + 'qwen-plus-latest: QWEN Plus Latest', + 'qwen-long: QWEN Long' + ], + 'gemini' => [ + 'gemini-2.0-flash: Gemini 2.0 Flash', + 'gemini-2.0-flash-lite-preview-02-05: Gemini 2.0 Flash-Lite Preview', + 'gemini-1.5-flash: Gemini 1.5 Flash', + 'gemini-1.5-flash-8b: Gemini 1.5 Flash 8B', + 'gemini-1.5-pro: Gemini 1.5 Pro', + 'gemini-1.0-pro: Gemini 1.0 Pro' + ], + 'zhipu' => [ + 'glm-4: GLM-4', + 'glm-4-plus: GLM-4 Plus', + 'glm-4-air: GLM-4 Air', + 'glm-4-airx: GLM-4 AirX', + 'glm-4-long: GLM-4 Long', + 'glm-4-flash: GLM-4 Flash', + 'glm-4v: GLM-4V', + 'glm-4v-plus: GLM-4V Plus', + 'glm-3-turbo: GLM-3 Turbo' + ], + default => [], + }; + } + + /** + * AI模型转数组 + * @param $models + * @param bool $retValue + * @return array + */ + public static function AIModels2Array($models, $retValue = false) + { + $list = is_array($models) ? $models : explode("\n", $models); + $array = []; + foreach ($list as $item) { + list($value, $label) = explode(':', $item . ':'); + if ($value) { + $array[] = [ + 'value' => trim($value), + 'label' => trim($label ?: $value) + ]; + } + } + if ($retValue) { + return array_column($array, 'value'); + } + return $array; + } + /** * 验证邮箱地址(过滤忽略地址) * @param $array diff --git a/app/Models/UserBot.php b/app/Models/UserBot.php index b62906a7e..5bbf1abc1 100644 --- a/app/Models/UserBot.php +++ b/app/Models/UserBot.php @@ -196,20 +196,23 @@ class UserBot extends AbstractModel ]; } $aibotSetting = Base::setting('aibotSetting'); + $aibotModel = $aibotSetting[$match[1] . '_model']; + $aibotModels = Setting::AIModels2Array($aibotSetting[$match[1] . '_models']); + if (empty($aibotModels)) { + return []; + } return [ [ 'key' => '~ai-model-select', 'label' => Doo::translate('选择模型'), 'config' => [ - 'model' => $aibotSetting[$match[1] . '_model'] + 'model' => $aibotModel, + 'models' => $aibotModels ] ], [ 'key' => '~ai-session-create', 'label' => Doo::translate('开启新会话'), - 'config' => [ - 'model' => $aibotSetting[$match[1] . '_model'] - ] ], [ 'key' => '~ai-session-history', diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index c2c5436bb..a9af9fe03 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -720,7 +720,6 @@ import touchclick from "../../../directives/touchclick"; import {languageList} from "../../../language"; import {isLocalResourcePath} from "../../../components/Replace/utils"; import emitter from "../../../store/events"; -import {AIModelLabel, AIModelList} from "../../../store/utils"; export default { name: "DialogWrapper", @@ -1848,9 +1847,16 @@ export default { if (key === '~ai-model-select') { const model = this.aiModelValue() if (model) { - label = AIModelLabel(this.dialogData.email, model) + label = model } else if (config?.model) { - label = AIModelLabel(this.dialogData.email, config.model) + label = config.model + } + if (config?.models) { + config.models.forEach(({value, label: text}) => { + if (value === label) { + label = text + } + }) } } return label @@ -1918,14 +1924,10 @@ export default { if (!this.isAiBot) { return } - const list = AIModelList(this.dialogData.email) - const configModel = item.config?.model - if (configModel && !list.find(({value}) => value === configModel)) { - list.unshift({label: configModel, value: configModel}) - } + const models = item.config?.models this.$store.state.menuOperation = { event, - list, + list: $A.isArray(models) ? models : [], scrollHide: true, onUpdate: async model => { this.dialogAiModel = [ diff --git a/resources/assets/js/pages/manage/setting/components/SystemAibot.vue b/resources/assets/js/pages/manage/setting/components/SystemAibot.vue index 8617040f6..836dbb9ff 100644 --- a/resources/assets/js/pages/manage/setting/components/SystemAibot.vue +++ b/resources/assets/js/pages/manage/setting/components/SystemAibot.vue @@ -19,20 +19,15 @@ :placeholder="$L(field.placeholder)"/> @@ -64,7 +59,6 @@