mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-15 05:12:49 +00:00
perf: AI机器人支持自定义模型
This commit is contained in:
parent
6bcc7b6c49
commit
fb286cea3c
@ -1028,6 +1028,7 @@ class DialogController extends AbstractController
|
|||||||
* @apiParam {String} [silence] 是否静默发送
|
* @apiParam {String} [silence] 是否静默发送
|
||||||
* - no: 正常发送(默认)
|
* - no: 正常发送(默认)
|
||||||
* - yes: 静默发送
|
* - yes: 静默发送
|
||||||
|
* @apiParam {String} [model_name] 模型名称(仅AI机器人支持)
|
||||||
*
|
*
|
||||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||||
@ -1048,6 +1049,7 @@ class DialogController extends AbstractController
|
|||||||
$key = trim(Request::input('key'));
|
$key = trim(Request::input('key'));
|
||||||
$text_type = strtolower(trim(Request::input('text_type')));
|
$text_type = strtolower(trim(Request::input('text_type')));
|
||||||
$silence = in_array(strtolower(trim(Request::input('silence'))), ['yes', 'true', '1']);
|
$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']);
|
$markdown = in_array($text_type, ['md', 'markdown']);
|
||||||
//
|
//
|
||||||
$result = [];
|
$result = [];
|
||||||
@ -1119,12 +1121,18 @@ class DialogController extends AbstractController
|
|||||||
if (empty($key)) {
|
if (empty($key)) {
|
||||||
$key = $desc;
|
$key = $desc;
|
||||||
}
|
}
|
||||||
|
if ($model_name) {
|
||||||
|
$msgData['model_name'] = $model_name;
|
||||||
|
}
|
||||||
$result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'longtext', $msgData, $user->userid, false, false, $silence, $key);
|
$result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'longtext', $msgData, $user->userid, false, false, $silence, $key);
|
||||||
} else {
|
} else {
|
||||||
$msgData = ['text' => $text];
|
$msgData = ['text' => $text];
|
||||||
if ($markdown) {
|
if ($markdown) {
|
||||||
$msgData['type'] = 'md';
|
$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);
|
$result = WebSocketDialogMsg::sendMsg($action, $dialog_id, 'text', $msgData, $user->userid, false, false, $silence, $key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -188,23 +188,25 @@ class UserBot extends AbstractModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (preg_match('/^ai-(.*?)@bot\.system$/', $email)) {
|
if (preg_match('/^ai-(.*?)@bot\.system$/', $email, $match)) {
|
||||||
if (!Base::judgeClientVersion('0.42.62')) {
|
if (!Base::judgeClientVersion('0.42.62')) {
|
||||||
return [
|
return [
|
||||||
'key' => '%3A.clear',
|
'key' => '%3A.clear',
|
||||||
'label' => Doo::translate('清空上下文')
|
'label' => Doo::translate('清空上下文')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
$aibotSetting = Base::setting('aibotSetting');
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
'key' => 'ai-newchat',
|
'key' => '~ai-model-select',
|
||||||
'label' => Doo::translate('开启新对话'),
|
'label' => Doo::translate('选择模型'),
|
||||||
'config' => []
|
'config' => [
|
||||||
|
'model' => $aibotSetting[$match[1] . '_model']
|
||||||
|
]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'key' => 'ai-historychat',
|
'key' => '%3A.clear',
|
||||||
'label' => Doo::translate('历史对话'),
|
'label' => Doo::translate('清空上下文')
|
||||||
'config' => []
|
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -431,6 +431,9 @@ class BotReceiveMsgTask extends AbstractTask
|
|||||||
'agency' => $setting[$type . '_agency'],
|
'agency' => $setting[$type . '_agency'],
|
||||||
'server_url' => $serverUrl,
|
'server_url' => $serverUrl,
|
||||||
];
|
];
|
||||||
|
if ($msg->msg['model_name']) {
|
||||||
|
$extras['model_name'] = $msg->msg['model_name'];
|
||||||
|
}
|
||||||
if ($type === 'wenxin') {
|
if ($type === 'wenxin') {
|
||||||
$extras['api_key'] .= ':' . $setting['wenxin_secret'];
|
$extras['api_key'] .= ':' . $setting['wenxin_secret'];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -256,7 +256,7 @@
|
|||||||
<div v-else-if="quickShow" class="chat-bottom-menu">
|
<div v-else-if="quickShow" class="chat-bottom-menu">
|
||||||
<ul class="scrollbar-hidden">
|
<ul class="scrollbar-hidden">
|
||||||
<li v-for="item in quickMsgs" @click.stop="sendQuick(item, $event)">
|
<li v-for="item in quickMsgs" @click.stop="sendQuick(item, $event)">
|
||||||
<div class="bottom-menu-desc no-dark-content" :style="item.style || null">{{item.label}}</div>
|
<div class="bottom-menu-desc no-dark-content" :style="item.style || null">{{quickLabel(item)}}</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -870,9 +870,14 @@ export default {
|
|||||||
replyMsgAutoMention: false, // 允许回复消息后自动@
|
replyMsgAutoMention: false, // 允许回复消息后自动@
|
||||||
waitUnreadData: new Map(), // 等待未读数据
|
waitUnreadData: new Map(), // 等待未读数据
|
||||||
replyEmojiIngs: {}, // 是否回复表情中(避免重复回复)
|
replyEmojiIngs: {}, // 是否回复表情中(避免重复回复)
|
||||||
|
dialogAiModel: [], // AI模型选择
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async created() {
|
||||||
|
this.dialogAiModel = await $A.IDBArray('dialogAiModel')
|
||||||
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.subMsgListener()
|
this.subMsgListener()
|
||||||
emitter.on('dialogMsgChange', this.onMsgChange);
|
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
|
* @param text
|
||||||
@ -1641,13 +1658,13 @@ export default {
|
|||||||
//
|
//
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
url: 'dialog/msg/sendtext',
|
url: 'dialog/msg/sendtext',
|
||||||
data: {
|
data: this.sendDataHandle({
|
||||||
dialog_id: this.dialogId,
|
dialog_id: this.dialogId,
|
||||||
update_id,
|
update_id,
|
||||||
text: textBody,
|
text: textBody,
|
||||||
text_type: textType,
|
text_type: textType,
|
||||||
silence,
|
silence,
|
||||||
},
|
}),
|
||||||
method: 'post',
|
method: 'post',
|
||||||
complete: _ => this.$store.dispatch("cancelLoad", `msg-${update_id}`)
|
complete: _ => this.$store.dispatch("cancelLoad", `msg-${update_id}`)
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
@ -1680,13 +1697,13 @@ export default {
|
|||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
requestId: tempMsg.id,
|
requestId: tempMsg.id,
|
||||||
url: 'dialog/msg/sendtext',
|
url: 'dialog/msg/sendtext',
|
||||||
data: {
|
data: this.sendDataHandle({
|
||||||
dialog_id: tempMsg.dialog_id,
|
dialog_id: tempMsg.dialog_id,
|
||||||
reply_id: tempMsg.reply_id,
|
reply_id: tempMsg.reply_id,
|
||||||
text: textBody,
|
text: textBody,
|
||||||
text_type: textType,
|
text_type: textType,
|
||||||
silence,
|
silence,
|
||||||
},
|
}),
|
||||||
method: 'post',
|
method: 'post',
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.sendSuccess(data, tempMsg.id)
|
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
|
* @param item
|
||||||
@ -1856,30 +1898,36 @@ export default {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 开启新对话
|
// 选择模型
|
||||||
case "ai-newchat":
|
case "~ai-model-select":
|
||||||
if (!this.isAiBot) {
|
if (!this.isAiBot) {
|
||||||
return
|
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 = {
|
this.$store.state.menuOperation = {
|
||||||
event,
|
event,
|
||||||
list: AIModelList(this.dialogData.email).map(value => ({label: value, value: value})),
|
list,
|
||||||
scrollHide: true,
|
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;
|
break;
|
||||||
|
|
||||||
// 历史对话
|
|
||||||
case "ai-historychat":
|
|
||||||
if (!this.isAiBot) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 发送快捷指令
|
// 发送快捷指令
|
||||||
default:
|
default:
|
||||||
|
if (/^~/.test(item.key)) {
|
||||||
|
$A.modalWarning("当前客户端不支持该指令");
|
||||||
|
break;
|
||||||
|
}
|
||||||
this.sendMsg(`<p><span data-quick-key="${item.key}">${item.label}</span></p>`)
|
this.sendMsg(`<p><span data-quick-key="${item.key}">${item.label}</span></p>`)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,7 +91,7 @@ export default {
|
|||||||
link: 'https://platform.openai.com/account/api-keys'
|
link: 'https://platform.openai.com/account/api-keys'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '模型',
|
label: '默认模型',
|
||||||
prop: 'openai_model',
|
prop: 'openai_model',
|
||||||
type: 'auto-complete',
|
type: 'auto-complete',
|
||||||
data: AIModelList('openai'),
|
data: AIModelList('openai'),
|
||||||
@ -132,7 +132,7 @@ export default {
|
|||||||
link: 'https://docs.anthropic.com/en/api/getting-started'
|
link: 'https://docs.anthropic.com/en/api/getting-started'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '模型',
|
label: '默认模型',
|
||||||
prop: 'claude_model',
|
prop: 'claude_model',
|
||||||
type: 'auto-complete',
|
type: 'auto-complete',
|
||||||
data: AIModelList('claude'),
|
data: AIModelList('claude'),
|
||||||
@ -167,7 +167,7 @@ export default {
|
|||||||
link: 'https://platform.deepseek.com/api_keys'
|
link: 'https://platform.deepseek.com/api_keys'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '模型',
|
label: '默认模型',
|
||||||
prop: 'deepseek_model',
|
prop: 'deepseek_model',
|
||||||
type: 'auto-complete',
|
type: 'auto-complete',
|
||||||
data: AIModelList('deepseek'),
|
data: AIModelList('deepseek'),
|
||||||
@ -208,7 +208,7 @@ export default {
|
|||||||
link: 'https://makersuite.google.com/app/apikey'
|
link: 'https://makersuite.google.com/app/apikey'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '模型',
|
label: '默认模型',
|
||||||
prop: 'gemini_model',
|
prop: 'gemini_model',
|
||||||
type: 'auto-complete',
|
type: 'auto-complete',
|
||||||
data: AIModelList('gemini'),
|
data: AIModelList('gemini'),
|
||||||
@ -242,7 +242,7 @@ export default {
|
|||||||
link: 'https://bigmodel.cn/usercenter/apikeys'
|
link: 'https://bigmodel.cn/usercenter/apikeys'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '模型',
|
label: '默认模型',
|
||||||
prop: 'zhipu_model',
|
prop: 'zhipu_model',
|
||||||
type: 'auto-complete',
|
type: 'auto-complete',
|
||||||
data: AIModelList('zhipu'),
|
data: AIModelList('zhipu'),
|
||||||
@ -276,7 +276,7 @@ export default {
|
|||||||
link: 'https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key'
|
link: 'https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '模型',
|
label: '默认模型',
|
||||||
prop: 'qianwen_model',
|
prop: 'qianwen_model',
|
||||||
type: 'auto-complete',
|
type: 'auto-complete',
|
||||||
data: AIModelList('qianwen'),
|
data: AIModelList('qianwen'),
|
||||||
@ -317,7 +317,7 @@ export default {
|
|||||||
link: 'https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application/v1'
|
link: 'https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application/v1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '模型',
|
label: '默认模型',
|
||||||
prop: 'wenxin_model',
|
prop: 'wenxin_model',
|
||||||
type: 'auto-complete',
|
type: 'auto-complete',
|
||||||
data: AIModelList('wenxin'),
|
data: AIModelList('wenxin'),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user