AiTaskPrepare.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. namespace App\Http\Api;
  3. use App\Models\AiModel;
  4. use App\Models\PaliSentence;
  5. use App\Models\PaliText;
  6. use App\Models\Sentence;
  7. use App\Models\Task;
  8. use App\Services\AuthService;
  9. class AiTaskPrepare
  10. {
  11. /**
  12. * 读取task信息,将任务拆解为单句小任务
  13. *
  14. * @param string $taskId 任务uuid
  15. * @return array 拆解后的提示词数组
  16. */
  17. public static function translate(string $taskId, bool $send = true)
  18. {
  19. $task = Task::findOrFail($taskId);
  20. $description = $task->description;
  21. $rows = explode("\n", $description);
  22. $params = [];
  23. foreach ($rows as $key => $row) {
  24. if (strpos($row, '=') !== false) {
  25. $param = explode('=', trim($row, '|'));
  26. $params[$param[0]] = $param[1];
  27. }
  28. }
  29. if (! isset($params['type'])) {
  30. return false;
  31. }
  32. // get sentences in article
  33. $sentences = [];
  34. $totalLen = 0;
  35. switch ($params['type']) {
  36. case 'sentence':
  37. if (! isset($params['id'])) {
  38. return false;
  39. }
  40. $sentences[] = explode('-', $params['id']);
  41. break;
  42. case 'para':
  43. if (! isset($params['book']) || ! isset($params['paragraphs'])) {
  44. return false;
  45. }
  46. $sent = PaliSentence::where('book', $params['book'])
  47. ->where('paragraph', $params['paragraphs'])->orderBy('word_begin')->get();
  48. foreach ($sent as $key => $value) {
  49. $sentences[] = [
  50. 'id' => [
  51. $value->book,
  52. $value->paragraph,
  53. $value->word_begin,
  54. $value->word_end,
  55. ],
  56. 'strlen' => $value->length,
  57. ];
  58. $totalLen += $value->length;
  59. }
  60. break;
  61. case 'chapter':
  62. if (! isset($params['book']) || ! isset($params['paragraphs'])) {
  63. return false;
  64. }
  65. $chapterLen = PaliText::where('book', $params['book'])
  66. ->where('paragraph', $params['paragraphs'])->value('chapter_len');
  67. $sent = PaliSentence::where('book', $params['book'])
  68. ->whereBetween('paragraph', [$params['paragraphs'], $params['paragraphs'] + $chapterLen - 1])
  69. ->orderBy('paragraph')
  70. ->orderBy('word_begin')->get();
  71. foreach ($sent as $key => $value) {
  72. $sentences[] = [
  73. 'id' => [
  74. $value->book,
  75. $value->paragraph,
  76. $value->word_begin,
  77. $value->word_end,
  78. ],
  79. 'strlen' => $value->length,
  80. ];
  81. $totalLen += $value->length;
  82. }
  83. break;
  84. default:
  85. return false;
  86. break;
  87. }
  88. // render prompt
  89. $mdRender = new MdRender([
  90. 'format' => 'prompt',
  91. 'footnote' => false,
  92. 'paragraph' => false,
  93. ]);
  94. $m = new \Mustache_Engine([
  95. 'entity_flags' => ENT_QUOTES,
  96. 'escape' => function ($value) {
  97. return $value;
  98. },
  99. ]);
  100. // ai model
  101. $aiModel = AiModel::findOrFail($task->executor_id);
  102. $modelToken = AuthService::getUserToken($aiModel->uid);
  103. $aiModel['token'] = $modelToken;
  104. $sumLen = 0;
  105. $mqData = [];
  106. foreach ($sentences as $key => $sentence) {
  107. $sumLen += $sentence['strlen'];
  108. $sid = implode('-', $sentence['id']);
  109. $sentChannelInfo = explode('@', $params['channel']);
  110. $channelId = $sentChannelInfo[0];
  111. $data = [];
  112. $data['origin'] = '{{'.$sid.'}}';
  113. $data['translation'] = '{{sent|id='.$sid;
  114. $data['translation'] .= '|channel='.$channelId;
  115. $data['translation'] .= '|text=translation}}';
  116. if (isset($params['nissaya']) && ! empty($params['nissaya'])) {
  117. $nissayaChannel = explode('@', $params['nissaya']);
  118. $channelInfo = ChannelApi::getById($nissayaChannel[0]);
  119. if ($channelInfo) {
  120. // 查看句子是否存在
  121. $nissayaSent = Sentence::where('book_id', $sentence['id'][0])
  122. ->where('paragraph', $sentence['id'][1])
  123. ->where('word_start', $sentence['id'][2])
  124. ->where('word_end', $sentence['id'][3])
  125. ->where('channel_uid', $nissayaChannel[0])->first();
  126. if ($nissayaSent && ! empty($nissayaSent->content)) {
  127. $nissayaData = [];
  128. $nissayaData['channel'] = $channelInfo;
  129. $nissayaData['data'] = '{{sent|id='.$sid;
  130. $nissayaData['data'] .= '|channel='.$nissayaChannel[0];
  131. $nissayaData['data'] .= '|text=translation}}';
  132. $data['nissaya'] = $nissayaData;
  133. }
  134. }
  135. }
  136. // Log::debug('mustache render', ['tpl' => $description, 'data' => $data]);
  137. $content = $m->render($description, $data);
  138. $prompt = $mdRender->convert($content, []);
  139. // gen mq
  140. $aiMqData = [
  141. 'model' => $aiModel,
  142. 'task' => [
  143. 'info' => $task,
  144. 'progress' => [
  145. 'current' => $sumLen,
  146. 'total' => $totalLen,
  147. ],
  148. ],
  149. 'prompt' => $prompt,
  150. 'sentence' => [
  151. 'book_id' => $sentence['id'][0],
  152. 'paragraph' => $sentence['id'][1],
  153. 'word_start' => $sentence['id'][2],
  154. 'word_end' => $sentence['id'][3],
  155. 'channel_uid' => $channelId,
  156. 'content' => $prompt,
  157. 'content_type' => 'markdown',
  158. 'access_token' => $sentChannelInfo[1] ?? $params['token'],
  159. ],
  160. ];
  161. array_push($mqData, $aiMqData);
  162. }
  163. if ($send) {
  164. Mq::publish('ai_translate', $mqData);
  165. }
  166. return $mqData;
  167. }
  168. }