AiTaskPrepare.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 Illuminate\Support\Facades\Log;
  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['para'])) {
  65. return false;
  66. }
  67. $chapterLen = PaliText::where('book', $params['book'])
  68. ->where('paragraph', $params['para'])->value('chapter_len');
  69. $sent = PaliSentence::where('book', $params['book'])
  70. ->whereBetween('paragraph', [$params['para'], $params['para'] + $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. $sumLen = 0;
  105. $mqData = [];
  106. foreach ($sentences as $key => $sentence) {
  107. $sumLen += $sentence['strlen'];
  108. $sid = implode('-', $sentence['id']);
  109. Log::debug($sid);
  110. $data['origin'] = '{{' . $sid . '}}';
  111. $data['translation'] = '{{sent|id=' . $sid;
  112. $data['translation'] .= '|channel=' . $params['channel'];
  113. $data['translation'] .= '|text=translation}}';
  114. if (isset($params['nissaya'])) {
  115. $data['nissaya'] = [];
  116. $nissayaChannels = explode(',', $params['nissaya']);
  117. foreach ($nissayaChannels as $key => $channel) {
  118. $channelInfo = ChannelApi::getById($channel);
  119. if (!$channelInfo) {
  120. continue;
  121. }
  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', $channel)->first();
  128. if (!$nissayaSent) {
  129. continue;
  130. }
  131. if (empty($nissayaSent->content)) {
  132. continue;
  133. }
  134. $nissayaData = [];
  135. $nissayaData['channel'] = $channelInfo;
  136. $nissayaData['data'] = '{{sent|id=' . $sid;
  137. $nissayaData['data'] .= '|channel=' . $channel;
  138. $nissayaData['data'] .= '|text=translation}}';
  139. $data['nissaya'][] = $nissayaData;
  140. }
  141. }
  142. $content = $m->render($description, $data);
  143. $prompt = $mdRender->convert($content, []);
  144. //gen mq
  145. $aiMqData = [
  146. 'model' => $aiModel,
  147. 'task' => [
  148. 'info' => $task,
  149. 'progress' => [
  150. 'current' => $sumLen,
  151. 'total' => $totalLen
  152. ],
  153. ],
  154. 'prompt' => $prompt,
  155. 'sentence' => [
  156. 'book_id' => $sentence['id'][0],
  157. 'paragraph' => $sentence['id'][1],
  158. 'word_start' => $sentence['id'][2],
  159. 'word_end' => $sentence['id'][3],
  160. 'channel_uid' => $params['channel'],
  161. 'content' => $prompt,
  162. 'content_type' => 'markdown',
  163. 'access_token' => $params['token'],
  164. ],
  165. ];
  166. array_push($mqData, $aiMqData);
  167. if ($send) {
  168. Mq::publish('ai_translate', $aiMqData);
  169. }
  170. }
  171. return $mqData;
  172. }
  173. }