2
0

AiTaskPrepare.php 6.9 KB

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