AiTaskPrepare.php 6.6 KB

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