diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 5929a831a..ee3cf5446 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -1028,6 +1028,7 @@ class DialogController extends AbstractController * @apiParam {String} [silence] 是否静默发送 * - no: 正常发送(默认) * - yes: 静默发送 + * @apiParam {String} [model_name] 模型名称(仅AI机器人支持) * * @apiSuccess {Number} ret 返回状态码(1正确、0错误) * @apiSuccess {String} msg 返回信息(错误描述) @@ -1048,6 +1049,7 @@ class DialogController extends AbstractController $key = trim(Request::input('key')); $text_type = strtolower(trim(Request::input('text_type'))); $silence = in_array(strtolower(trim(Request::input('silence'))), ['yes', 'true', '1']); + $model_name = trim(Request::input('model_name')); $markdown = in_array($text_type, ['md', 'markdown']); // $result = []; @@ -1119,12 +1121,18 @@ class DialogController extends AbstractController if (empty($key)) { $key = $desc; } + if ($model_name) { + $msgData['model_name'] = $model_name; + } $result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'longtext', $msgData, $user->userid, false, false, $silence, $key); } else { $msgData = ['text' => $text]; if ($markdown) { $msgData['type'] = 'md'; } + if ($model_name) { + $msgData['model_name'] = $model_name; + } $result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'text', $msgData, $user->userid, false, false, $silence, $key); } } diff --git a/app/Models/UserBot.php b/app/Models/UserBot.php index a16d3e653..bedeafb5d 100644 --- a/app/Models/UserBot.php +++ b/app/Models/UserBot.php @@ -188,23 +188,25 @@ class UserBot extends AbstractModel ]; default: - if (preg_match('/^ai-(.*?)@bot\.system$/', $email)) { + if (preg_match('/^ai-(.*?)@bot\.system$/', $email, $match)) { if (!Base::judgeClientVersion('0.42.62')) { return [ 'key' => '%3A.clear', 'label' => Doo::translate('清空上下文') ]; } + $aibotSetting = Base::setting('aibotSetting'); return [ [ - 'key' => 'ai-newchat', - 'label' => Doo::translate('开启新对话'), - 'config' => [] + 'key' => '~ai-model-select', + 'label' => Doo::translate('选择模型'), + 'config' => [ + 'model' => $aibotSetting[$match[1] . '_model'] + ] ], [ - 'key' => 'ai-historychat', - 'label' => Doo::translate('历史对话'), - 'config' => [] + 'key' => '%3A.clear', + 'label' => Doo::translate('清空上下文') ] ]; } diff --git a/app/Tasks/BotReceiveMsgTask.php b/app/Tasks/BotReceiveMsgTask.php index a3e9e5fae..9d5721079 100644 --- a/app/Tasks/BotReceiveMsgTask.php +++ b/app/Tasks/BotReceiveMsgTask.php @@ -431,6 +431,9 @@ class BotReceiveMsgTask extends AbstractTask 'agency' => $setting[$type . '_agency'], 'server_url' => $serverUrl, ]; + if ($msg->msg['model_name']) { + $extras['model_name'] = $msg->msg['model_name']; + } if ($type === 'wenxin') { $extras['api_key'] .= ':' . $setting['wenxin_secret']; } diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index cbd013a0e..895722682 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -256,7 +256,7 @@
@@ -870,9 +870,14 @@ export default { replyMsgAutoMention: false, // 允许回复消息后自动@ waitUnreadData: new Map(), // 等待未读数据 replyEmojiIngs: {}, // 是否回复表情中(避免重复回复) + dialogAiModel: [], // AI模型选择 } }, + async created() { + this.dialogAiModel = await $A.IDBArray('dialogAiModel') + }, + mounted() { this.subMsgListener() emitter.on('dialogMsgChange', this.onMsgChange); @@ -1594,6 +1599,18 @@ export default { } }, + /** + * 发送数据处理 + * @param data + * @returns {*} + */ + sendDataHandle(data) { + if (this.isAiBot) { + data.model_name = this.aiModelValue() + } + return data + }, + /** * 发送消息 * @param text @@ -1641,13 +1658,13 @@ export default { // this.$store.dispatch("call", { url: 'dialog/msg/sendtext', - data: { + data: this.sendDataHandle({ dialog_id: this.dialogId, update_id, text: textBody, text_type: textType, silence, - }, + }), method: 'post', complete: _ => this.$store.dispatch("cancelLoad", `msg-${update_id}`) }).then(({data}) => { @@ -1680,13 +1697,13 @@ export default { this.$store.dispatch("call", { requestId: tempMsg.id, url: 'dialog/msg/sendtext', - data: { + data: this.sendDataHandle({ dialog_id: tempMsg.dialog_id, reply_id: tempMsg.reply_id, text: textBody, text_type: textType, silence, - }, + }), method: 'post', }).then(({data}) => { this.sendSuccess(data, tempMsg.id) @@ -1799,6 +1816,31 @@ export default { }); }, + /** + * Ai模型值 + * @returns {*} + */ + aiModelValue() { + const item = this.dialogAiModel.find(({dialog_id}) => dialog_id == this.dialogId) + return item?.model + }, + + /** + * 快捷菜单标签 + * @param key + * @param label + * @param config + * @returns {*} + */ + quickLabel({key, label, config}) { + if (key === '~ai-model-select') { + const model = this.aiModelValue() + if (model) return model + if (config?.model) return config.model + } + return label + }, + /** * 发送快捷消息 * @param item @@ -1856,30 +1898,36 @@ export default { }); break; - // 开启新对话 - case "ai-newchat": + // 选择模型 + case "~ai-model-select": if (!this.isAiBot) { return } + const list = AIModelList(this.dialogData.email).map(value => ({label: value, value: value})) + const configModel = item.config?.model + if (configModel && !list.find(({value}) => value === configModel)) { + list.unshift({label: configModel, value: configModel}) + } this.$store.state.menuOperation = { event, - list: AIModelList(this.dialogData.email).map(value => ({label: value, value: value})), + list, scrollHide: true, - onUpdate: async (model) => { - + onUpdate: async model => { + this.dialogAiModel = [ + ...this.dialogAiModel.filter(({dialog_id}) => dialog_id !== this.dialogId), + {dialog_id: this.dialogId, model} + ] + await $A.IDBSet('dialogAiModel', this.dialogAiModel) } } break; - // 历史对话 - case "ai-historychat": - if (!this.isAiBot) { - return - } - break; - // 发送快捷指令 default: + if (/^~/.test(item.key)) { + $A.modalWarning("当前客户端不支持该指令"); + break; + } this.sendMsg(`${item.label}
`) break; } diff --git a/resources/assets/js/pages/manage/setting/components/SystemAibot.vue b/resources/assets/js/pages/manage/setting/components/SystemAibot.vue index 3d1f9604c..5f70c4d01 100644 --- a/resources/assets/js/pages/manage/setting/components/SystemAibot.vue +++ b/resources/assets/js/pages/manage/setting/components/SystemAibot.vue @@ -91,7 +91,7 @@ export default { link: 'https://platform.openai.com/account/api-keys' }, { - label: '模型', + label: '默认模型', prop: 'openai_model', type: 'auto-complete', data: AIModelList('openai'), @@ -132,7 +132,7 @@ export default { link: 'https://docs.anthropic.com/en/api/getting-started' }, { - label: '模型', + label: '默认模型', prop: 'claude_model', type: 'auto-complete', data: AIModelList('claude'), @@ -167,7 +167,7 @@ export default { link: 'https://platform.deepseek.com/api_keys' }, { - label: '模型', + label: '默认模型', prop: 'deepseek_model', type: 'auto-complete', data: AIModelList('deepseek'), @@ -208,7 +208,7 @@ export default { link: 'https://makersuite.google.com/app/apikey' }, { - label: '模型', + label: '默认模型', prop: 'gemini_model', type: 'auto-complete', data: AIModelList('gemini'), @@ -242,7 +242,7 @@ export default { link: 'https://bigmodel.cn/usercenter/apikeys' }, { - label: '模型', + label: '默认模型', prop: 'zhipu_model', type: 'auto-complete', data: AIModelList('zhipu'), @@ -276,7 +276,7 @@ export default { link: 'https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key' }, { - label: '模型', + label: '默认模型', prop: 'qianwen_model', type: 'auto-complete', data: AIModelList('qianwen'), @@ -317,7 +317,7 @@ export default { link: 'https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application/v1' }, { - label: '模型', + label: '默认模型', prop: 'wenxin_model', type: 'auto-complete', data: AIModelList('wenxin'),