perf: 支持在AI对话中直接引用任务提问

This commit is contained in:
kuaifan 2025-02-22 17:49:11 +08:00
parent e97806c85b
commit 6ae46cf7bb
2 changed files with 108 additions and 39 deletions

View File

@ -12,6 +12,7 @@ use App\Tasks\PushTask;
use App\Exceptions\ApiException; use App\Exceptions\ApiException;
use App\Observers\ProjectTaskObserver; use App\Observers\ProjectTaskObserver;
use Hhxsv5\LaravelS\Swoole\Task\Task; use Hhxsv5\LaravelS\Swoole\Task\Task;
use League\HTMLToMarkdown\HtmlConverter;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
@ -1869,6 +1870,66 @@ class ProjectTask extends AbstractModel
return true; 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;
}
}
if ($this->content) {
$taskDesc = $this->content?->getContentInfo();
if ($taskDesc) {
$converter = new HtmlConverter(['strip_tags' => true]);
$descContent = Base::cutStr($converter->convert($taskDesc['content']), 2000);
$contexts[] = <<<EOF
任务描述:
```md
{$descContent}
```
EOF;
}
}
$subTask = ProjectTask::select(['id', 'name', 'complete_at', 'end_at'])->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[] = <<<EOF
子任务列表:
{$subTaskContent}
EOF;
}
}
return $contexts;
}
/** /**
* 获取任务 * 获取任务
* @param $task_id * @param $task_id

View File

@ -12,9 +12,9 @@ use App\Models\WebSocketDialogMsg;
use App\Module\Base; use App\Module\Base;
use App\Module\Doo; use App\Module\Doo;
use App\Module\Ihttp; use App\Module\Ihttp;
use Cache;
use Carbon\Carbon; use Carbon\Carbon;
use DB; use DB;
use League\HTMLToMarkdown\HtmlConverter;
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); @error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
@ -452,13 +452,30 @@ class BotReceiveMsgTask extends AbstractTask
if (in_array($this->client['platform'], ['win', 'mac', 'web']) && !Base::judgeClientVersion("0.41.11", $this->client['version'])) { if (in_array($this->client['platform'], ['win', 'mac', 'web']) && !Base::judgeClientVersion("0.41.11", $this->client['version'])) {
$errorContent = '当前客户端版本低所需版本≥v0.41.11)。'; $errorContent = '当前客户端版本低所需版本≥v0.41.11)。';
} }
$attachments = Cache::get("bot:{$msg->id}:attachments");
if ($attachments) {
$command = <<<EOF
原始问题:{$command}
{$attachments}
EOF;
}
if ($msg->reply_id > 0) { if ($msg->reply_id > 0) {
$replyMsg = WebSocketDialogMsg::find($msg->reply_id); $replyMsg = WebSocketDialogMsg::find($msg->reply_id);
$replyCommand = ''; $replyCommand = '';
if ($replyMsg) { if ($replyMsg) {
$replyCommand = $this->extractCommand($replyMsg); $replyCommand = $this->extractCommand($replyMsg);
if ($replyCommand) { if ($replyCommand) {
$replyCommand = "<quoted>" . Base::cutStr($replyCommand, 2000) . "</quoted>\n\nThe content within the above <quoted> tags is a citation.\n\n"; $replyCommand = Base::cutStr($replyCommand, 2000);
$replyCommand = <<<EOF
<quoted>
{$replyCommand}
</quoted>
上述 quoted 标签内的内容为引用。
EOF;
} }
} }
$command = $replyCommand . $command; $command = $replyCommand . $command;
@ -563,6 +580,31 @@ class BotReceiveMsgTask extends AbstractTask
$command = ":" . substr($command, 4); $command = ":" . substr($command, 4);
} }
} else { } else {
$attachments = [];
if (preg_match_all("/<span class=\"mention task\" data-id=\"(\d+)\">(.*?)<\/span>/", $original, $match)) {
$taskIds = Base::newIntval($match[1]);
foreach ($taskIds as $index => $taskId) {
$taskInfo = ProjectTask::with(['content'])->whereId($taskId)->first();
if ($taskInfo) {
$taskContext = implode("\n", $taskInfo->AIContext());
$attachments[] = <<<EOF
任务【{$taskInfo->name}
{$taskContext}
EOF;
} else {
$attachments[] = <<<EOF
任务【{$match[2][$index]}
任务状态:不存在或已删除
EOF;
}
}
if ($attachments) {
array_unshift($attachments, "相关任务信息:");
}
}
if ($attachments) {
Cache::put("bot:{$msg->id}:attachments", implode("\n\n", $attachments), 60);
}
$command = trim(strip_tags($original)); $command = trim(strip_tags($original));
} }
if (empty($command)) { if (empty($command)) {
@ -625,45 +667,11 @@ class BotReceiveMsgTask extends AbstractTask
$taskInfo = ProjectTask::with(['content'])->whereDialogId($dialog->id)->first(); $taskInfo = ProjectTask::with(['content'])->whereDialogId($dialog->id)->first();
if ($taskInfo) { if ($taskInfo) {
$taskText = "当前我在任务【{$taskInfo->name}】中"; $taskText = "当前我在任务【{$taskInfo->name}】中";
if ($taskInfo->archived_at) { $taskContext = implode("\n", $taskInfo->AIContext());
$taskText .= ",此任务已经归档"; if ($taskContext) {
} elseif ($taskInfo->complete_at) { $taskText .= "\n{$taskContext}";
$taskText .= ",此任务已经完成";
} elseif ($taskInfo->end_at && Carbon::parse($taskInfo->end_at)->lt(Carbon::now())) {
$taskText .= ",此任务已经过期";
} }
$before_text[] = $taskText; $before_text[] = $taskText;
if ($taskInfo->content) {
$taskDesc = $taskInfo->content?->getContentInfo();
if ($taskDesc) {
$converter = new HtmlConverter(['strip_tags' => true]);
$descContent = Base::cutStr($converter->convert($taskDesc['content']), 2000);
$before_text[] = <<<EOF
任务描述:
```md
{$descContent}
```
EOF;
}
}
$subTask = ProjectTask::select(['id', 'name', 'complete_at', 'end_at'])->whereParentId($taskInfo->id)->get();
if ($subTask->isNotEmpty()) {
$subTaskContent = $subTask->map(function($item) {
$status = "";
if ($item->complete_at) {
$status = " (已完成)";
} elseif ($item->end_at && Carbon::parse($item->end_at)->lt(Carbon::now())) {
$status = " (已过期)";
}
return " - {$item->name} {$status}";
})->join("\n");
if ($subTaskContent) {
$before_text[] = <<<EOF
子任务列表:
{$subTaskContent}
EOF;
}
}
$before_text[] = <<<EOF $before_text[] = <<<EOF
如果你判断我想要添加子任务,请按照以下格式回复: 如果你判断我想要添加子任务,请按照以下格式回复: