AiTaskPrepare.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. Log::error('no $params.type');
  33. return false;
  34. }
  35. //get sentences in article
  36. $sentences = array();
  37. $totalLen = 0;
  38. switch ($params['type']) {
  39. case 'sentence':
  40. if (!isset($params['id'])) {
  41. Log::error('no $params.id');
  42. return false;
  43. }
  44. $sentences[] = explode('-', $params['id']);
  45. break;
  46. case 'para':
  47. if (!isset($params['book']) || !isset($params['paragraphs'])) {
  48. Log::error('no $params.book or paragraphs');
  49. return false;
  50. }
  51. $sent = PaliSentence::where('book', $params['book'])
  52. ->where('paragraph', $params['paragraphs'])->orderBy('word_begin')->get();
  53. foreach ($sent as $key => $value) {
  54. $sentences[] = [
  55. 'id' => [
  56. $value->book,
  57. $value->paragraph,
  58. $value->word_begin,
  59. $value->word_end,
  60. ],
  61. 'strlen' => $value->length
  62. ];
  63. $totalLen += $value->length;
  64. }
  65. break;
  66. case 'chapter':
  67. if (!isset($params['book']) || !isset($params['paragraphs'])) {
  68. Log::error('no $params.book or paragraphs');
  69. return false;
  70. }
  71. $chapterLen = PaliText::where('book', $params['book'])
  72. ->where('paragraph', $params['paragraphs'])->value('chapter_len');
  73. $sent = PaliSentence::where('book', $params['book'])
  74. ->whereBetween('paragraph', [$params['paragraphs'], $params['paragraphs'] + $chapterLen - 1])
  75. ->orderBy('paragraph')
  76. ->orderBy('word_begin')->get();
  77. foreach ($sent as $key => $value) {
  78. $sentences[] = [
  79. 'id' => [
  80. $value->book,
  81. $value->paragraph,
  82. $value->word_begin,
  83. $value->word_end,
  84. ],
  85. 'strlen' => $value->length
  86. ];
  87. $totalLen += $value->length;
  88. }
  89. break;
  90. default:
  91. return false;
  92. break;
  93. }
  94. //render prompt
  95. $mdRender = new MdRender([
  96. 'format' => 'prompt',
  97. 'footnote' => false,
  98. 'paragraph' => false,
  99. ]);
  100. $m = new \Mustache_Engine(array(
  101. 'entity_flags' => ENT_QUOTES,
  102. 'escape' => function ($value) {
  103. return $value;
  104. }
  105. ));
  106. # ai model
  107. $aiModel = AiModel::findOrFail($task->executor_id);
  108. $sumLen = 0;
  109. $mqData = [];
  110. foreach ($sentences as $key => $sentence) {
  111. $sumLen += $sentence['strlen'];
  112. $sid = implode('-', $sentence['id']);
  113. Log::debug($sid);
  114. $sentChannelInfo = explode('@', $params['channel']);
  115. $channelId = $sentChannelInfo[0];
  116. $data = [];
  117. $data['origin'] = '{{' . $sid . '}}';
  118. $data['translation'] = '{{sent|id=' . $sid;
  119. $data['translation'] .= '|channel=' . $channelId;
  120. $data['translation'] .= '|text=translation}}';
  121. if (isset($params['nissaya']) && !empty($params['nissaya'])) {
  122. $nissayaArray = [];
  123. $nissayaChannels = explode(',', $params['nissaya']);
  124. foreach ($nissayaChannels as $key => $channel) {
  125. $nissayaChannel = explode('@', $channel);
  126. $channelInfo = ChannelApi::getById($nissayaChannel[0]);
  127. if (!$channelInfo) {
  128. continue;
  129. }
  130. //查看句子是否存在
  131. $nissayaSent = Sentence::where('book_id', $sentence['id'][0])
  132. ->where('paragraph', $sentence['id'][1])
  133. ->where('word_start', $sentence['id'][2])
  134. ->where('word_end', $sentence['id'][3])
  135. ->where('channel_uid', $nissayaChannel[0])->first();
  136. if (!$nissayaSent) {
  137. continue;
  138. }
  139. if (empty($nissayaSent->content)) {
  140. continue;
  141. }
  142. $nissayaData = [];
  143. $nissayaData['channel'] = $channelInfo;
  144. $nissayaData['data'] = '{{sent|id=' . $sid;
  145. $nissayaData['data'] .= '|channel=' . $nissayaChannel[0];
  146. $nissayaData['data'] .= '|text=translation}}';
  147. $nissayaArray[] = $nissayaData;
  148. }
  149. }
  150. if (isset($nissayaArray) && count($nissayaArray) > 0) {
  151. $data['nissaya'] = $nissayaArray;
  152. }
  153. Log::debug('mustache render', ['tpl' => $description, 'data' => $data]);
  154. $content = $m->render($description, $data);
  155. $prompt = $mdRender->convert($content, []);
  156. //gen mq
  157. $aiMqData = [
  158. 'model' => $aiModel,
  159. 'task' => [
  160. 'info' => $task,
  161. 'progress' => [
  162. 'current' => $sumLen,
  163. 'total' => $totalLen
  164. ],
  165. ],
  166. 'prompt' => $prompt,
  167. 'sentence' => [
  168. 'book_id' => $sentence['id'][0],
  169. 'paragraph' => $sentence['id'][1],
  170. 'word_start' => $sentence['id'][2],
  171. 'word_end' => $sentence['id'][3],
  172. 'channel_uid' => $channelId,
  173. 'content' => $prompt,
  174. 'content_type' => 'markdown',
  175. 'access_token' => $sentChannelInfo[1] ?? $params['token'],
  176. ],
  177. ];
  178. array_push($mqData, $aiMqData);
  179. if ($send) {
  180. Mq::publish('ai_translate', $aiMqData);
  181. }
  182. }
  183. return $mqData;
  184. }
  185. }