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