mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-14 12:42:51 +00:00
perf: 机器人支持新会话
This commit is contained in:
parent
b406e22695
commit
0b86fa7bee
@ -3291,15 +3291,7 @@ class DialogController extends AbstractController
|
||||
$dialog = WebSocketDialog::checkDialog($dialog_id);
|
||||
}
|
||||
//
|
||||
if ($dialog->type != 'user') {
|
||||
return Base::retError('当前对话不支持');
|
||||
}
|
||||
//
|
||||
$hasAiUser = WebSocketDialogUser::join('users as u', 'web_socket_dialog_users.userid', '=', 'u.userid')
|
||||
->where('dialog_id', $dialog->id)
|
||||
->where('u.email', 'like', 'ai-%@bot.system')
|
||||
->exists();
|
||||
if (!$hasAiUser) {
|
||||
if (!$dialog->isSessionDialog()) {
|
||||
return Base::retError('当前对话不支持');
|
||||
}
|
||||
//
|
||||
@ -3312,7 +3304,6 @@ class DialogController extends AbstractController
|
||||
//
|
||||
$session = WebSocketDialogSession::create([
|
||||
'dialog_id' => $dialog->id,
|
||||
'status' => 1,
|
||||
'title' => '',
|
||||
]);
|
||||
$session->save();
|
||||
|
||||
@ -376,7 +376,7 @@ class UsersController extends AbstractController
|
||||
public function info__departments()
|
||||
{
|
||||
$user = User::auth();
|
||||
|
||||
|
||||
// 获取部门列表
|
||||
$list = UserDepartment::select(['id', 'owner_userid', 'parent_id', 'name'])
|
||||
->whereIn('id', $user->department)
|
||||
@ -2103,6 +2103,11 @@ class UsersController extends AbstractController
|
||||
* @apiParam {Number} [id] 机器人ID(编辑时必填,留空为添加)
|
||||
* @apiParam {String} [name] 机器人名称
|
||||
* @apiParam {String} [avatar] 机器人头像
|
||||
* @apiParam {Number} [session] 开启新会话功能(仅 我的机器人)
|
||||
* - 1:开启、0:关闭, 默认:0
|
||||
* - 此参数仅在添加机器人时有效
|
||||
* - 开启后,机器人对话窗口会出现新会话菜单和历史会话菜单
|
||||
* - 开启后,webhook_url 消息会多一个 session_id 字段
|
||||
* @apiParam {Number} [clear_day] 清理天数(仅 我的机器人)
|
||||
* @apiParam {String} [webhook_url] Webhook地址(仅 我的机器人)
|
||||
*
|
||||
@ -2115,8 +2120,9 @@ class UsersController extends AbstractController
|
||||
$user = User::auth();
|
||||
//
|
||||
$botId = intval(Request::input('id'));
|
||||
$session = intval(Request::input('session'));
|
||||
if (empty($botId)) {
|
||||
$res = UserBot::newbot($user->userid, trim(Request::input('name')));
|
||||
$res = UserBot::newBot($user->userid, trim(Request::input('name')), (bool)$session);
|
||||
if (Base::isError($res)) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
@ -174,10 +174,9 @@ class User extends AbstractModel
|
||||
return UserDepartment::where('owner_userid', $this->userid)->exists();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取机器人所有者
|
||||
* @return int|mixed
|
||||
* @return int
|
||||
*/
|
||||
public function getBotOwner()
|
||||
{
|
||||
@ -782,18 +781,17 @@ class User extends AbstractModel
|
||||
/**
|
||||
* 是否机器人
|
||||
* @param $userid
|
||||
* @return bool|mixed
|
||||
* @return bool
|
||||
*/
|
||||
public static function isBot($userid)
|
||||
{
|
||||
if (empty($userid)) {
|
||||
return false;
|
||||
}
|
||||
$userid = intval($userid);
|
||||
if (RequestContext::has("isBot_" . $userid)) {
|
||||
return RequestContext::get("isBot_" . $userid);
|
||||
}
|
||||
return (bool)User::find($userid)?->bot;
|
||||
// 这个不会有变化,所以可以使用永久缓存
|
||||
return (bool)Cache::rememberForever('is-bot-user-' . $userid, function () use ($userid) {
|
||||
return (bool)User::find($userid)?->bot;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -180,28 +180,8 @@ class UserBot extends AbstractModel
|
||||
];
|
||||
|
||||
default:
|
||||
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');
|
||||
$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' => $aibotModel,
|
||||
'models' => $aibotModels
|
||||
]
|
||||
],
|
||||
if (preg_match('/^(ai-|user-session-)(.*?)@bot\.system$/', $email, $match)) {
|
||||
$menus = [
|
||||
[
|
||||
'key' => '~ai-session-create',
|
||||
'label' => Doo::translate('开启新会话'),
|
||||
@ -211,6 +191,27 @@ class UserBot extends AbstractModel
|
||||
'label' => Doo::translate('历史会话'),
|
||||
]
|
||||
];
|
||||
if ($match[1] === "ai-") {
|
||||
$aibotSetting = Base::setting('aibotSetting');
|
||||
$aibotModel = $aibotSetting[$match[1] . '_model'];
|
||||
$aibotModels = Setting::AIModels2Array($aibotSetting[$match[1] . '_models']);
|
||||
if ($aibotModels) {
|
||||
$menus = array_merge(
|
||||
[
|
||||
[
|
||||
'key' => '~ai-model-select',
|
||||
'label' => Doo::translate('选择模型'),
|
||||
'config' => [
|
||||
'model' => $aibotModel,
|
||||
'models' => $aibotModels
|
||||
]
|
||||
]
|
||||
],
|
||||
$menus
|
||||
);
|
||||
}
|
||||
}
|
||||
return $menus;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@ -445,11 +446,12 @@ class UserBot extends AbstractModel
|
||||
|
||||
/**
|
||||
* 创建我的机器人
|
||||
* @param $userid
|
||||
* @param $botName
|
||||
* @param int $userid 创建人userid
|
||||
* @param string $botName 机器人名称
|
||||
* @param bool $sessionSupported 是否支持会话
|
||||
* @return array
|
||||
*/
|
||||
public static function newbot($userid, $botName)
|
||||
public static function newBot($userid, $botName, $sessionSupported = false)
|
||||
{
|
||||
if (User::select(['users.*'])
|
||||
->join('user_bots', 'users.userid', '=', 'user_bots.bot_id')
|
||||
@ -461,7 +463,8 @@ class UserBot extends AbstractModel
|
||||
if (strlen($botName) < 2 || strlen($botName) > 20) {
|
||||
return Base::retError("机器人名称由2-20个字符组成。");
|
||||
}
|
||||
$data = User::botGetOrCreate("user-" . Base::generatePassword(), [
|
||||
$botType = ($sessionSupported ? "user-session-" : "user-normal-") . Base::generatePassword();
|
||||
$data = User::botGetOrCreate($botType, [
|
||||
'nickname' => $botName
|
||||
], $userid);
|
||||
if (empty($data)) {
|
||||
@ -469,6 +472,15 @@ class UserBot extends AbstractModel
|
||||
}
|
||||
$dialog = WebSocketDialog::checkUserDialog($data, $userid);
|
||||
if ($dialog) {
|
||||
if ($sessionSupported) {
|
||||
$dialogSession = WebSocketDialogSession::create([
|
||||
'dialog_id' => $dialog->id,
|
||||
'title' => 'Default',
|
||||
]);
|
||||
$dialogSession->save();
|
||||
$dialog->session_id = $dialogSession->id;
|
||||
$dialog->save();
|
||||
}
|
||||
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'template', [
|
||||
'type' => '/hello',
|
||||
'title' => '创建成功。',
|
||||
|
||||
@ -705,6 +705,27 @@ class WebSocketDialog extends AbstractModel
|
||||
return WebSocketDialogUser::whereDialogId($this->id)->where('userid', '>', 0)->count() === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否支持创建会话
|
||||
* @return bool
|
||||
*/
|
||||
public function isSessionDialog()
|
||||
{
|
||||
// 这个不会有变化,所以可以使用永久缓存
|
||||
return Cache::rememberForever('is-session-dialog-' . $this->id, function () {
|
||||
if ($this->type !== 'user') {
|
||||
return false;
|
||||
}
|
||||
$data = $this->dialogUserBuilder()->get();
|
||||
foreach ($data as $item) {
|
||||
if (preg_match('/^(ai-|user-session-)(.*?)@bot\.system$/', $item->email)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否是AI对话
|
||||
* @return bool
|
||||
@ -799,6 +820,7 @@ class WebSocketDialog extends AbstractModel
|
||||
WebSocketDialogUser::createInstance([
|
||||
'dialog_id' => $dialog->id,
|
||||
'userid' => $value,
|
||||
'bot' => User::isBot($value) ? 1 : 0,
|
||||
'important' => !in_array($group_type, ['user', 'all']),
|
||||
'last_at' => in_array($group_type, ['user', 'department', 'all']) ? Carbon::now() : null,
|
||||
])->save();
|
||||
@ -835,16 +857,17 @@ class WebSocketDialog extends AbstractModel
|
||||
WebSocketDialogUser::createInstance([
|
||||
'dialog_id' => $dialog->id,
|
||||
'userid' => $user->userid,
|
||||
'bot' => User::isBot($user->userid) ? 1 : 0,
|
||||
])->save();
|
||||
WebSocketDialogUser::createInstance([
|
||||
'dialog_id' => $dialog->id,
|
||||
'userid' => $receiver,
|
||||
'bot' => User::isBot($receiver) ? 1 : 0,
|
||||
])->save();
|
||||
//
|
||||
if ($user->isAiBot() || User::find($receiver)?->isAiBot()) {
|
||||
$session = WebSocketDialogSession::create([
|
||||
'dialog_id' => $dialog->id,
|
||||
'status' => 1,
|
||||
'title' => '',
|
||||
]);
|
||||
$session->save();
|
||||
|
||||
@ -205,7 +205,7 @@ class BotReceiveMsgTask extends AbstractTask
|
||||
* 创建
|
||||
*/
|
||||
case '/newbot':
|
||||
$res = UserBot::newbot($msg->userid, $array[1]);
|
||||
$res = UserBot::newBot($msg->userid, $array[1]);
|
||||
if (Base::isError($res)) {
|
||||
$content = $res['msg'];
|
||||
} else {
|
||||
@ -381,6 +381,7 @@ class BotReceiveMsgTask extends AbstractTask
|
||||
default => '不支持的指令',
|
||||
};
|
||||
if ($type == '/api') {
|
||||
$msgData['email'] = $botUser->email;
|
||||
$msgData['version'] = Base::getVersion();
|
||||
} elseif ($type == '/help') {
|
||||
$msgData['manager'] = $isManager;
|
||||
@ -522,6 +523,7 @@ class BotReceiveMsgTask extends AbstractTask
|
||||
'text' => $command,
|
||||
'reply_text' => $replyText,
|
||||
'token' => User::generateToken($botUser),
|
||||
'session_id' => $dialog->session_id,
|
||||
'dialog_id' => $dialog->id,
|
||||
'dialog_type' => $dialog->type,
|
||||
'msg_id' => $msg->id,
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
<p><span class="mark-color">text</span>: {{$L("消息文本")}}</p>
|
||||
<p><span class="mark-color">reply_text</span>: {{$L("回复/引用消息文本")}}</p>
|
||||
<p><span class="mark-color">token</span>: {{$L("机器人Token")}}</p>
|
||||
<p v-if="/^(ai-|user-session-)/.test(msg.email)"><span class="mark-color">session_id</span>: {{$L("会话ID")}}</p>
|
||||
<p><span class="mark-color">dialog_id</span>: {{$L("对话ID")}}</p>
|
||||
<p><span class="mark-color">dialog_type</span>: {{$L("对话类型")}}</p>
|
||||
<p><span class="mark-color">msg_id</span>: {{$L("消息ID")}}</p>
|
||||
|
||||
@ -1917,13 +1917,6 @@ export default {
|
||||
|
||||
// 开启新会话
|
||||
case "~ai-session-create":
|
||||
if (!this.isAiBot) {
|
||||
return
|
||||
}
|
||||
// 清理会话本地缓存
|
||||
this.$store.dispatch("clearDialogMsgs", {
|
||||
id: this.dialogId
|
||||
});
|
||||
// 创建新会话
|
||||
this.$store.dispatch("call", {
|
||||
url: 'dialog/session/create',
|
||||
@ -1940,9 +1933,6 @@ export default {
|
||||
|
||||
// 历史会话
|
||||
case "~ai-session-history":
|
||||
if (!this.isAiBot) {
|
||||
return
|
||||
}
|
||||
this.sessionHistoryData = {
|
||||
dialog_id: this.dialogId,
|
||||
name: this.dialogData.name,
|
||||
|
||||
@ -250,10 +250,6 @@ export default {
|
||||
const processQueue = async () => {
|
||||
try {
|
||||
for (const user of this.aiUser) {
|
||||
// 清理会话本地缓存
|
||||
this.$store.dispatch("clearDialogMsgs", {
|
||||
id: this.dialogId
|
||||
});
|
||||
// 创建新会话
|
||||
await this.$store.dispatch("call", {
|
||||
url: 'dialog/session/create',
|
||||
@ -261,6 +257,10 @@ export default {
|
||||
userid: user.userid,
|
||||
},
|
||||
});
|
||||
// 清理会话本地缓存
|
||||
await this.$store.dispatch("clearDialogMsgs", {
|
||||
id: this.dialogId
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
} catch (error) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user