diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index aca8a6ca7..0fe03d296 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -33,7 +33,6 @@ use App\Models\WebSocketDialogSession; use App\Models\UserRecentItem; use App\Module\Table\OnlineData; use App\Module\ZincSearch\ZincSearchDialogMsg; -use App\Tasks\BotReceiveMsgTask; use Hhxsv5\LaravelS\Swoole\Task\Task; /** @@ -2494,33 +2493,6 @@ class DialogController extends AbstractController return Base::retSuccess("success", $data); } - /** - * @api {post} api/dialog/msg/webhookmsg2ai 转换为AI对话 - * - * @apiDescription 需要token身份,将webhook消息转换为适合AI对话的格式消息,用于AI对话 - * @apiVersion 1.0.0 - * @apiGroup dialog - * @apiName msg__webhookmsg2ai - * - * @apiParam {String} msg 消息内容 - * - * @apiSuccess {Number} ret 返回状态码(1正确、0错误) - * @apiSuccess {String} msg 返回信息(错误描述) - * @apiSuccess {Object} data 返回数据 - */ - public function msg__webhookmsg2ai() - { - User::auth(); - // - $msg = Request::input('msg'); - try { - $res = BotReceiveMsgTask::convertMentionForAI($msg); - return Base::retSuccess("success", ['msg' => $res]); - } catch (\Exception $e) { - return Base::retError($e->getMessage()); - } - } - /** * @api {get} api/dialog/group/add 新增群组 * diff --git a/app/Models/ProjectTask.php b/app/Models/ProjectTask.php index 6c7953eee..b12efb656 100644 --- a/app/Models/ProjectTask.php +++ b/app/Models/ProjectTask.php @@ -1948,66 +1948,6 @@ class ProjectTask extends AbstractModel return true; } - /** - * 生成AI上下文 - * @return array - */ - public function AIContext() - { - $contexts = []; - if ($this->archived_at) { - $contexts[] = "任务状态:已归档"; - $contexts[] = "归档时间:" . $this->archived_at; - } elseif ($this->complete_at) { - $contexts[] = "任务状态:已完成"; - $contexts[] = "完成时间:" . $this->complete_at; - } elseif ($this->end_at && Carbon::parse($this->end_at)->lt(Carbon::now())) { - $contexts[] = "任务状态:已过期"; - $contexts[] = "任务截止时间:" . $this->end_at; - } else { - $contexts[] = "任务状态:进行中"; - if ($this->start_at) { - $contexts[] = "任务开始时间:" . $this->start_at; - } - if ($this->end_at) { - $contexts[] = "任务截止时间:" . $this->end_at; - } - } - $contexts[] = "当前系统时间:" . Carbon::now()->toDateTimeString(); - if ($this->content) { - $taskDesc = $this->content?->getContentInfo(); - if ($taskDesc) { - $descContent = Base::cutStr(Base::html2markdown($taskDesc['content'], ['strip_tags' => true]), 2000); - $contexts[] = <<whereParentId($this->id)->get(); - if ($subTask->isNotEmpty()) { - $subTaskContent = $subTask->map(function($item) { - if ($item->complete_at) { - $status = " (已完成)"; - } elseif ($item->end_at && Carbon::parse($item->end_at)->lt(Carbon::now())) { - $status = " (已过期)"; - } else { - $status = " (进行中)"; - } - return " - {$item->name} {$status}"; - })->join("\n"); - if ($subTaskContent) { - $contexts[] = <<type) { case "file": // 提取文件消息 - $msgData = Base::json2array($this->getRawOriginal('msg')); - $result = $this->convertMentionFormat("path", $msgData['path'], $msgData['name'], $reserves); + $result = " 文件:{$this->msg['name']}、大小:{$this->msg['size']}、下载URL:{$this->msg['path']} "; break; case "text": @@ -889,29 +888,31 @@ class WebSocketDialogMsg extends AbstractModel // 提及任务、文件、报告 $result = preg_replace_callback_array([ // 用户 - "/(.*?)<\/span>/" => function () { - return ""; + "/(.*?)<\/span>/" => function ($match) { + return " 提及用户ID:{$match[1]} "; }, // 任务 - "/#?(.*?)<\/span>/" => function ($match) use (&$reserves) { - return $this->convertMentionFormat("task", $match[1], $match[2], $reserves); + "/#?(.*?)<\/span>/" => function ($match) { + return " 任务:{$match[2]} (任务ID:{$match[1]}) "; }, // 文件 "/]*?>~?(.*?)<\/a>/" => function ($match) use (&$reserves) { + $idOrCode = ""; if (preg_match("/single\/file\/(.*?)$/", $match[1], $subMatch)) { - return $this->convertMentionFormat("file", $subMatch[1], $match[2], $reserves); + $idOrCode = " (" . (Base::isNumber($subMatch[1]) ? "文件ID:{$subMatch[1]}" : "文件分享码:{$subMatch[1]}") . ")"; } - return ""; + return " 文件:{$match[2]}{$idOrCode} "; }, // 报告 "/]*?>%?(.*?)<\/a>/" => function ($match) use (&$reserves) { + $idOrCode = ""; if (preg_match("/single\/report\/detail\/(.*?)$/", $match[1], $subMatch)) { - return $this->convertMentionFormat("report", $subMatch[1], $match[2], $reserves); + $idOrCode = " (" . (Base::isNumber($subMatch[1]) ? "报告ID:{$subMatch[1]}" : "报告分享码:{$subMatch[1]}") . ")"; } - return ""; + return " 工作汇报:{$match[2]}{$idOrCode} "; }, ], $result); @@ -926,11 +927,6 @@ class WebSocketDialogMsg extends AbstractModel return ''; } - // 处理 reserves - foreach ($reserves as $rand => $mention) { - $result = str_replace($rand, $mention, $result); - } - // 截取最大长度 if ($maxLength > 0 && mb_strlen($result) > $maxLength) { $result = mb_substr($result, 0, $maxLength); @@ -939,24 +935,6 @@ class WebSocketDialogMsg extends AbstractModel return $result; } - /** - * 转换提及消息格式 - * 将提及的任务、文件、报告等转换为统一的格式 [type#key#name] - * - * @param string $type 提及类型(task、file、report、path) - * @param string $key 提及对象的唯一标识 - * @param string $name 提及对象的显示名称 - * @return string 格式化后的提及字符串 - */ - private function convertMentionFormat($type, $key, $name, &$reserves) - { - $key = str_replace(['#', '-->'], '', $key); - $name = str_replace(['#', '-->'], '', $name); - $rand = Base::generatePassword(12); - $reserves[$rand] = ""; - return $rand; - } - /** * 处理文本消息内容,用于发送前 * @param $text diff --git a/app/Tasks/BotReceiveMsgTask.php b/app/Tasks/BotReceiveMsgTask.php index 127fc760f..4a151f79e 100644 --- a/app/Tasks/BotReceiveMsgTask.php +++ b/app/Tasks/BotReceiveMsgTask.php @@ -510,15 +510,13 @@ class BotReceiveMsgTask extends AbstractTask } $this->generateSystemPromptForAI($msg->userid, $dialog, $extras); // 转换提及格式 - $sendText = self::convertMentionForAI($sendText); - $replyText = self::convertMentionForAI($replyText); if ($replyText) { $sendText = << {$replyText} - The content within the above quoted_content tags is a citation. + 上述 quoted_content 标签中的内容为引用。 {$sendText} EOF; @@ -598,99 +596,6 @@ class BotReceiveMsgTask extends AbstractTask } } - /** - * 为AI机器人转换提及消息格式 - * 将提及的任务、文件、报告转换为AI可理解的格式,并提取相关内容 - * - * @param string $original 原始消息文本 - * @return string 转换后的消息文本,包含相关内容的标签 - * @throws Exception 当提及的对象不存在或读取失败时抛出异常 - */ - public static function convertMentionForAI($original) - { - $array = []; - $original = preg_replace_callback('//', function ($match) use (&$array) { - // 初始化 tag 内容 - $pathTag = null; - $pathName = null; - $pathContent = null; - - // 根据 type 提取 tag 内容 - switch ($match[1]) { - // 任务 - case 'task': - $taskInfo = ProjectTask::with(['content'])->whereId(intval($match[2]))->first(); - if (!$taskInfo) { - throw new Exception("任务不存在或已被删除"); - } - $pathTag = "task_content"; - $pathName = addslashes($taskInfo->name) . " (ID:{$taskInfo->id})"; - $pathContent = implode("\n", $taskInfo->AIContext()); - break; - - // 文件 - case 'file': - $fileInfo = FileContent::idOrCodeToContent($match[2]); - if (!$fileInfo || !isset($fileInfo->content['url'])) { - throw new Exception("文件不存在或已被删除"); - } - $urlPath = public_path($fileInfo->content['url']); - if (!file_exists($urlPath)) { - throw new Exception("文件不存在或已被删除"); - } - $fileResult = TextExtractor::extractFile($urlPath); - if (Base::isError($fileResult)) { - throw new Exception("文件读取失败:" . $fileResult['msg']); - } - $pathTag = "file_content"; - $pathName = addslashes($match[3]) . " (ID:{$fileInfo->id})"; - $pathContent = $fileResult['data']; - break; - - // 文件路径 - case 'path': - $urlPath = public_path($match[2]); - if (!file_exists($urlPath)) { - throw new Exception("文件不存在或已被删除"); - } - $fileResult = TextExtractor::extractFile($urlPath); - if (Base::isError($fileResult)) { - throw new Exception("文件读取失败:" . $fileResult['msg']); - } - $pathTag = "file_content"; - $pathName = addslashes($match[3]); - $pathContent = $fileResult['data']; - break; - - // 报告 - case 'report': - $reportInfo = Report::idOrCodeToContent($match[2]); - if (!$reportInfo) { - throw new Exception("报告不存在或已被删除"); - } - $pathTag = "report_content"; - $pathName = addslashes($match[3]) . " (ID:{$reportInfo->id})"; - $pathContent = Base::html2markdown($reportInfo->content); - break; - } - - // 如果提取到 tag 内容,则添加到 contents 数组中 - if ($pathTag) { - $array[] = "<{$pathTag} path=\"{$pathName}\">\n{$pathContent}\n"; - return "`{$pathName}` (see below for {$pathTag} tag)"; - } - - return ""; - }, $original); - - // 添加 tag 内容 - if ($array) { - $original .= "\n\n" . implode("\n\n", $array); - } - - return $original; - } - /** * 为AI机器人生成系统提示词 * 根据对话类型(用户对话、项目群、任务群、部门群等)生成相应的系统提示词 @@ -739,29 +644,15 @@ class BotReceiveMsgTask extends AbstractTask case 'project': $projectInfo = Project::whereDialogId($dialog->id)->first(); if ($projectInfo) { - $projectDesc = $projectInfo->desc ?: "-"; - $projectStatus = $projectInfo->archived_at ? '已归档' : '正在进行中'; + $currentTime = Carbon::now()->toDateTimeString(); $sections[] = << - 当前我在项目【{$projectInfo->name}】中 - 项目描述:{$projectDesc} - 项目状态:{$projectStatus} + 当前我在项目群聊中 + 项目ID:{$projectInfo->id} + 项目名称:{$projectInfo->name} + 当前时间:{$currentTime} EOF; - - $sections[] = << - 如果你判断我想要或需要添加任务,请按照以下格式回复: - - ::: create-task-list - title: 任务标题1 - desc: 任务描述1 - - title: 任务标题2 - desc: 任务描述2 - ::: - - EOF; } break; @@ -769,26 +660,15 @@ class BotReceiveMsgTask extends AbstractTask case 'task': $taskInfo = ProjectTask::with(['content'])->whereDialogId($dialog->id)->first(); if ($taskInfo) { - $taskContext = implode("\n", $taskInfo->AIContext()); + $currentTime = Carbon::now()->toDateTimeString(); $sections[] = << - 当前我在任务【{$taskInfo->name}】中 - 当前时间:{$taskInfo->updated_at} + 当前我在任务群聊中 任务ID:{$taskInfo->id} - {$taskContext} + 任务名称:{$taskInfo->name} + 当前时间:{$currentTime} EOF; - - $sections[] = << - 如果你判断我想要或需要添加子任务,请按照以下格式回复: - - ::: create-subtask-list - title: 子任务标题1 - title: 子任务标题2 - ::: - - EOF; } break; @@ -798,7 +678,9 @@ class BotReceiveMsgTask extends AbstractTask if ($userDepartment) { $sections[] = << - 当前我在【{$userDepartment->name}】的部门群聊中 + 当前我在部门群聊中 + 部门ID:{$userDepartment->id} + 部门名称:{$userDepartment->name} EOF; } @@ -836,7 +718,6 @@ class BotReceiveMsgTask extends AbstractTask // 添加标签说明 $tagDescs = [ 'role_setting' => '你的基础角色和行为定义', - 'instructions' => '特定功能的操作指令', 'context_info' => '当前环境和状态信息', 'chat_history' => '最近的对话历史记录', ];