mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-11 18:42:54 +00:00
feat: 优化WebSocketDialogMsg和BotReceiveMsgTask中的消息格式,统一中文标点,增强可读性
This commit is contained in:
parent
eb9b7b4f86
commit
8af6887daa
@ -834,7 +834,7 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
switch ($this->type) {
|
switch ($this->type) {
|
||||||
case "file":
|
case "file":
|
||||||
// 提取文件消息
|
// 提取文件消息
|
||||||
$result = " 文件:{$this->msg['name']}、大小:{$this->msg['size']}、下载URL:{$this->msg['path']} ";
|
$result = " 文件:{$this->msg['name']}(大小:{$this->msg['size']}B,URL:{$this->msg['path']}) ";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "text":
|
case "text":
|
||||||
@ -858,30 +858,30 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
$result = preg_replace_callback_array([
|
$result = preg_replace_callback_array([
|
||||||
// 用户
|
// 用户
|
||||||
"/<span class=\"mention user\" data-id=\"(\d+)\">(.*?)<\/span>/" => function ($match) {
|
"/<span class=\"mention user\" data-id=\"(\d+)\">(.*?)<\/span>/" => function ($match) {
|
||||||
return " 提及用户ID:{$match[1]} ";
|
return "";
|
||||||
},
|
},
|
||||||
|
|
||||||
// 任务
|
// 任务
|
||||||
"/<span class=\"mention task\" data-id=\"(\d+)\">#?(.*?)<\/span>/" => function ($match) {
|
"/<span class=\"mention task\" data-id=\"(\d+)\">#?(.*?)<\/span>/" => function ($match) {
|
||||||
return " 任务:{$match[2]} (任务ID:{$match[1]}) ";
|
return " 任务:{$match[2]} (任务ID:{$match[1]}) ";
|
||||||
},
|
},
|
||||||
|
|
||||||
// 文件
|
// 文件
|
||||||
"/<a class=\"mention file\" href=\"([^\"']+?)\"[^>]*?>~?(.*?)<\/a>/" => function ($match) use (&$reserves) {
|
"/<a class=\"mention file\" href=\"([^\"']+?)\"[^>]*?>~?(.*?)<\/a>/" => function ($match) use (&$reserves) {
|
||||||
$idOrCode = "";
|
$idOrCode = "";
|
||||||
if (preg_match("/single\/file\/(.*?)$/", $match[1], $subMatch)) {
|
if (preg_match("/single\/file\/(.*?)$/", $match[1], $subMatch)) {
|
||||||
$idOrCode = " (" . (Base::isNumber($subMatch[1]) ? "文件ID:{$subMatch[1]}" : "文件分享码:{$subMatch[1]}") . ")";
|
$idOrCode = " (" . (Base::isNumber($subMatch[1]) ? "文件ID:{$subMatch[1]}" : "文件分享码:{$subMatch[1]}") . ")";
|
||||||
}
|
}
|
||||||
return " 文件:{$match[2]}{$idOrCode} ";
|
return " 文件:{$match[2]}{$idOrCode} ";
|
||||||
},
|
},
|
||||||
|
|
||||||
// 报告
|
// 报告
|
||||||
"/<a class=\"mention report\" href=\"([^\"']+?)\"[^>]*?>%?(.*?)<\/a>/" => function ($match) use (&$reserves) {
|
"/<a class=\"mention report\" href=\"([^\"']+?)\"[^>]*?>%?(.*?)<\/a>/" => function ($match) use (&$reserves) {
|
||||||
$idOrCode = "";
|
$idOrCode = "";
|
||||||
if (preg_match("/single\/report\/detail\/(.*?)$/", $match[1], $subMatch)) {
|
if (preg_match("/single\/report\/detail\/(.*?)$/", $match[1], $subMatch)) {
|
||||||
$idOrCode = " (" . (Base::isNumber($subMatch[1]) ? "报告ID:{$subMatch[1]}" : "报告分享码:{$subMatch[1]}") . ")";
|
$idOrCode = " (" . (Base::isNumber($subMatch[1]) ? "报告ID:{$subMatch[1]}" : "报告分享码:{$subMatch[1]}") . ")";
|
||||||
}
|
}
|
||||||
return " 工作汇报:{$match[2]}{$idOrCode} ";
|
return " 工作汇报:{$match[2]}{$idOrCode} ";
|
||||||
},
|
},
|
||||||
], $result);
|
], $result);
|
||||||
|
|
||||||
|
|||||||
@ -508,7 +508,7 @@ class BotReceiveMsgTask extends AbstractTask
|
|||||||
if (empty($extras['api_key'])) {
|
if (empty($extras['api_key'])) {
|
||||||
throw new Exception('机器人未启用。');
|
throw new Exception('机器人未启用。');
|
||||||
}
|
}
|
||||||
$this->generateSystemPromptForAI($msg->userid, $dialog, $extras);
|
$this->generateSystemPromptForAI($msg->userid, $dialog, $botUser, $extras);
|
||||||
// 转换提及格式
|
// 转换提及格式
|
||||||
if ($replyText) {
|
if ($replyText) {
|
||||||
$sendText = <<<EOF
|
$sendText = <<<EOF
|
||||||
@ -602,134 +602,80 @@ class BotReceiveMsgTask extends AbstractTask
|
|||||||
*
|
*
|
||||||
* @param int|null $userid 用户ID
|
* @param int|null $userid 用户ID
|
||||||
* @param WebSocketDialog $dialog 对话对象
|
* @param WebSocketDialog $dialog 对话对象
|
||||||
|
* @param User $botUser 机器人用户对象
|
||||||
* @param array $extras 额外参数数组,通过引用传递以修改system_message
|
* @param array $extras 额外参数数组,通过引用传递以修改system_message
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function generateSystemPromptForAI($userid, WebSocketDialog $dialog, array &$extras)
|
private function generateSystemPromptForAI($userid, WebSocketDialog $dialog, User $botUser, array &$extras)
|
||||||
{
|
{
|
||||||
// 构建结构化的系统提示词
|
// 用户自定义提示词(私聊场景优先使用)
|
||||||
$sections = [];
|
$customPrompt = null;
|
||||||
|
if ($dialog->type === 'user') {
|
||||||
// 基础角色设定(如果有)
|
$customPrompt = WebSocketDialogConfig::where([
|
||||||
if (!empty($extras['system_message'])) {
|
'dialog_id' => $dialog->id,
|
||||||
$sections[] = <<<EOF
|
'userid' => $userid,
|
||||||
<role_setting>
|
'type' => 'ai_prompt',
|
||||||
{$extras['system_message']}
|
])->value('value');
|
||||||
</role_setting>
|
|
||||||
EOF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上下文信息(项目、任务、部门等)+ 操作指令
|
$prompt = [];
|
||||||
switch ($dialog->type) {
|
|
||||||
// 用户对话
|
|
||||||
case "user":
|
|
||||||
$aiPrompt = WebSocketDialogConfig::where([
|
|
||||||
'dialog_id' => $dialog->id,
|
|
||||||
'userid' => $userid,
|
|
||||||
'type' => 'ai_prompt',
|
|
||||||
])->value('value');
|
|
||||||
if ($aiPrompt) {
|
|
||||||
return $aiPrompt;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 群组对话
|
// 1. 基础角色(自定义提示词优先)
|
||||||
case "group":
|
if ($customPrompt) {
|
||||||
switch ($dialog->group_type) {
|
$prompt[] = $customPrompt;
|
||||||
// 用户群
|
} elseif (!empty($extras['system_message'])) {
|
||||||
case 'user':
|
$prompt[] = $extras['system_message'];
|
||||||
break;
|
|
||||||
|
|
||||||
// 项目群
|
|
||||||
case 'project':
|
|
||||||
$projectInfo = Project::whereDialogId($dialog->id)->first();
|
|
||||||
if ($projectInfo) {
|
|
||||||
$currentTime = Carbon::now()->toDateTimeString();
|
|
||||||
$sections[] = <<<EOF
|
|
||||||
<context_info>
|
|
||||||
当前我在项目群聊中
|
|
||||||
项目ID:{$projectInfo->id}
|
|
||||||
项目名称:{$projectInfo->name}
|
|
||||||
当前时间:{$currentTime}
|
|
||||||
</context_info>
|
|
||||||
EOF;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 任务群
|
|
||||||
case 'task':
|
|
||||||
$taskInfo = ProjectTask::with(['content'])->whereDialogId($dialog->id)->first();
|
|
||||||
if ($taskInfo) {
|
|
||||||
$currentTime = Carbon::now()->toDateTimeString();
|
|
||||||
$sections[] = <<<EOF
|
|
||||||
<context_info>
|
|
||||||
当前我在任务群聊中
|
|
||||||
任务ID:{$taskInfo->id}
|
|
||||||
任务名称:{$taskInfo->name}
|
|
||||||
当前时间:{$currentTime}
|
|
||||||
</context_info>
|
|
||||||
EOF;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 部门群
|
|
||||||
case 'department':
|
|
||||||
$userDepartment = UserDepartment::whereDialogId($dialog->id)->first();
|
|
||||||
if ($userDepartment) {
|
|
||||||
$sections[] = <<<EOF
|
|
||||||
<context_info>
|
|
||||||
当前我在部门群聊中
|
|
||||||
部门ID:{$userDepartment->id}
|
|
||||||
部门名称:{$userDepartment->name}
|
|
||||||
</context_info>
|
|
||||||
EOF;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 全体成员群
|
|
||||||
case 'all':
|
|
||||||
$sections[] = <<<EOF
|
|
||||||
<context_info>
|
|
||||||
当前我在【全体成员】的群聊中
|
|
||||||
</context_info>
|
|
||||||
EOF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 聊天历史
|
|
||||||
if ($dialog->type === 'group') {
|
|
||||||
$chatHistory = $this->getRecentChatHistory($dialog, 15);
|
|
||||||
if ($chatHistory) {
|
|
||||||
$sections[] = <<<EOF
|
|
||||||
<chat_history>
|
|
||||||
{$chatHistory}
|
|
||||||
</chat_history>
|
|
||||||
EOF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新系统提示词
|
// 2. 上下文信息
|
||||||
if (!empty($sections)) {
|
$currentTime = Carbon::now()->toDateTimeString();
|
||||||
$extras['system_message'] = implode("\n\n", $sections);
|
$contextLines = [
|
||||||
}
|
"您是:{$botUser->nickname}(ID: {$botUser->userid})",
|
||||||
|
"当前对话ID:{$dialog->id}",
|
||||||
// 添加标签说明
|
"当前系统时间:{$currentTime}"
|
||||||
$tagDescs = [
|
|
||||||
'role_setting' => '你的基础角色和行为定义',
|
|
||||||
'context_info' => '当前环境和状态信息',
|
|
||||||
'chat_history' => '最近的对话历史记录',
|
|
||||||
];
|
];
|
||||||
$useTags = [];
|
|
||||||
foreach ($tagDescs as $tag => $desc) {
|
if ($dialog->type === 'group') {
|
||||||
if (str_contains($extras['system_message'], '<' . $tag . '>')) {
|
switch ($dialog->group_type) {
|
||||||
$useTags[] = '- <' . $tag . '>: ' . $desc;
|
case 'project':
|
||||||
|
$projectInfo = Project::whereDialogId($dialog->id)->first();
|
||||||
|
if ($projectInfo) {
|
||||||
|
$contextLines[] = "场景:项目群聊「{$projectInfo->name}」(ID: {$projectInfo->id})";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'task':
|
||||||
|
$taskInfo = ProjectTask::with(['content'])->whereDialogId($dialog->id)->first();
|
||||||
|
if ($taskInfo) {
|
||||||
|
$contextLines[] = "场景:任务群聊「{$taskInfo->name}」(ID: {$taskInfo->id})";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'department':
|
||||||
|
$userDepartment = UserDepartment::whereDialogId($dialog->id)->first();
|
||||||
|
if ($userDepartment) {
|
||||||
|
$contextLines[] = "场景:部门群聊「{$userDepartment->name}」";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'all':
|
||||||
|
$contextLines[] = "场景:全体成员群聊";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. 聊天历史(仅群聊)
|
||||||
|
$chatHistory = $this->getRecentChatHistory($dialog, 15);
|
||||||
|
if ($chatHistory) {
|
||||||
|
$prompt[] = implode("\n", $contextLines);
|
||||||
|
$prompt[] = "最近的对话记录:\n{$chatHistory}";
|
||||||
|
} else {
|
||||||
|
$prompt[] = implode("\n", $contextLines);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$prompt[] = implode("\n", $contextLines);
|
||||||
}
|
}
|
||||||
if (!empty($useTags)) {
|
|
||||||
$extras['system_message'] = "以下信息按标签组织:\n" . implode("\n", $useTags) . "\n\n" . $extras['system_message'];
|
$extras['system_message'] = implode("\n----\n", array_filter($prompt));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -766,14 +712,14 @@ class BotReceiveMsgTask extends AbstractTask
|
|||||||
// 使用XML标签格式,确保AI能清晰识别边界
|
// 使用XML标签格式,确保AI能清晰识别边界
|
||||||
// 对用户名进行HTML转义,防止特殊字符破坏格式
|
// 对用户名进行HTML转义,防止特殊字符破坏格式
|
||||||
$safeUserName = htmlspecialchars($userName, ENT_QUOTES, 'UTF-8');
|
$safeUserName = htmlspecialchars($userName, ENT_QUOTES, 'UTF-8');
|
||||||
return "<message user=\"{$safeUserName}\">\n{$content}\n</message>";
|
return "<message userid=\"{$message->userid}\" nickname=\"{$safeUserName}\">\n{$content}\n</message>";
|
||||||
})
|
})
|
||||||
->reverse() // 反转集合,让时间顺序正确(最早的在前)
|
->reverse() // 反转集合,让时间顺序正确(最早的在前)
|
||||||
->filter() // 过滤掉空内容的消息
|
->filter() // 过滤掉空内容的消息
|
||||||
->values() // 重新索引数组
|
->values() // 重新索引数组
|
||||||
->toArray();
|
->toArray();
|
||||||
|
|
||||||
return empty($chatMessages) ? null : implode("\n\n", $chatMessages);
|
return empty($chatMessages) ? null : implode("\n", $chatMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user