缅文的中文译文 3. note:缅文注释的中文译文 3. confidence:两个译文的语义相似度(0-100) 示例输入: {"original":"buddha","translation":"ဗုဒ္ဓ","note":"အဘိဓာန်"} 示例输出: {"original":"buddha","translation":"佛>佛陀","note":"词汇表","confidence":100} 请翻译以下内容: PROMPT; public function __construct( OpenAIService $openAIService, NissayaParser $nissayaParser, RomanizeService $romanizeService ) { $this->openAIService = $openAIService; $this->nissayaParser = $nissayaParser; $this->romanizeService = $romanizeService; $this->romanize = true; } /** * 设置模型配置 * * @param \App\Http\Resources\AiModelResource $model * @return self */ public function setModel(AiModelResource $model): self { $this->model = $model; return $this; } /** * 设置翻译提示词 * * @param string $prompt * @return self */ public function setTranslatePrompt(string $prompt): self { $this->translatePrompt = $prompt; return $this; } /** * 设置翻译提示词 * * @param string $prompt * @return self */ public function setRomanize(bool $romanize): self { $this->romanize = $romanize; return $this; } /** * 翻译缅文版逐词解析 * * @param string $text 格式: 巴利文=缅文 * @param bool $stream 是否流式输出 * @return array * @throws \Exception */ public function translate(string $text, bool $stream = false): array { $startAt = time(); try { // 1. 解析nissaya文本为数组 $parsedData = $this->nissayaParser->parse($text); if (empty($parsedData)) { throw new \Exception('解析nissaya文本失败,返回空数组'); } $parsedData = $this->romanize($parsedData); foreach ($parsedData as $key => $value) { if (isset($value['notes']) && is_array($value['notes'])) { $parsedData[$key]['note'] = implode("\n\n----\n\n", $value['notes']); $parsedData[$key]['note'] = str_replace("\n**", "\n\n-----\n\n", $parsedData[$key]['note']); unset($parsedData[$key]['notes']); } } // 2. 将解析后的数组转换为JSONL格式 $jsonlInput = $this->arrayToJsonl($parsedData); Log::info('NissayaTranslate: 准备翻译', [ 'items_count' => count($parsedData), 'input_length' => strlen($jsonlInput), ]); // 3. 调用LLM进行翻译 $response = $this->openAIService ->setApiUrl($this->model['url']) ->setModel($this->model['model']) ->setApiKey($this->model['key']) ->setSystemPrompt($this->translatePrompt) ->setTemperature(0.3) ->setStream($stream) ->send($jsonlInput); $complete = time() - $startAt; $content = $response['choices'][0]['message']['content'] ?? ''; if (empty($content)) { throw new \Exception('LLM返回内容为空'); } // 4. 解析JSONL格式的翻译结果 $translatedData = $this->jsonlToArray($content); Log::info('NissayaTranslate: 翻译完成', [ 'duration' => $complete, 'output_items' => count($translatedData), 'input_tokens' => $response['usage']['prompt_tokens'] ?? 0, 'output_tokens' => $response['usage']['completion_tokens'] ?? 0, ]); return [ 'success' => true, 'data' => $translatedData, 'meta' => [ 'duration' => $complete, 'items_count' => count($translatedData), 'usage' => $response['usage'] ?? [], ], ]; } catch (\Exception $e) { Log::error('NissayaTranslate: 翻译失败', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); return [ 'success' => false, 'error' => $e->getMessage(), 'data' => [], ]; } } protected function romanize(array $data): array { if ($this->romanize) { foreach ($data as $key => $value) { $data[$key]['original'] = $this->romanizeService->myanmarToRoman($value['original']); } } return $data; } /** * 将数组转换为JSONL格式 * * @param array $data * @return string */ protected function arrayToJsonl(array $data): string { $lines = []; foreach ($data as $item) { $lines[] = json_encode($item, JSON_UNESCAPED_UNICODE); } return implode("\n", $lines); } /** * 将JSONL格式转换为数组 * * @param string $jsonl * @return array */ protected function jsonlToArray(string $jsonl): array { // 清理可能的markdown代码块标记 $jsonl = preg_replace('/```json\s*|\s*```/', '', $jsonl); $jsonl = trim($jsonl); $lines = explode("\n", $jsonl); $result = []; foreach ($lines as $line) { $line = trim($line); if (empty($line)) { continue; } $decoded = json_decode($line, true); if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) { $result[] = $decoded; } else { Log::warning('NissayaTranslate: 无法解析JSON行', [ 'line' => $line, 'error' => json_last_error_msg(), ]); } } return $result; } /** * 批量翻译(将大文本分批处理) * * @param string $text * @param int $batchSize 每批处理的条目数 * @return array */ public function translateInBatches(string $text, int $batchSize = 50): array { try { $parsedData = $this->nissayaParser->parse($text); $batches = array_chunk($parsedData, $batchSize); $allResults = []; $totalDuration = 0; $totalUsage = [ 'prompt_tokens' => 0, 'completion_tokens' => 0, 'total_tokens' => 0, ]; foreach ($batches as $index => $batch) { Log::info("NissayaTranslate: 处理批次 " . ($index + 1) . "/" . count($batches)); $jsonlInput = $this->arrayToJsonl($batch); $response = $this->openAIService ->setApiUrl($this->model['url']) ->setModel($this->model['model']) ->setApiKey($this->model['key']) ->setSystemPrompt($this->translatePrompt) ->setTemperature(0.7) ->setStream(false) ->send($jsonlInput); $content = $response['choices'][0]['message']['content'] ?? ''; $translatedBatch = $this->jsonlToArray($content); $allResults = array_merge($allResults, $translatedBatch); // 累计使用统计 if (isset($response['usage'])) { $totalUsage['prompt_tokens'] += $response['usage']['prompt_tokens'] ?? 0; $totalUsage['completion_tokens'] += $response['usage']['completion_tokens'] ?? 0; $totalUsage['total_tokens'] += $response['usage']['total_tokens'] ?? 0; } } return [ 'success' => true, 'data' => $allResults, 'meta' => [ 'batches' => count($batches), 'items_count' => count($allResults), 'usage' => $totalUsage, ], ]; } catch (\Exception $e) { Log::error('NissayaTranslate: 批量翻译失败', [ 'error' => $e->getMessage(), ]); return [ 'success' => false, 'error' => $e->getMessage(), 'data' => [], ]; } } }