58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
# app/translators/smart_engine.py
|
|
import json
|
|
import os
|
|
from typing import List
|
|
|
|
from openai import OpenAI
|
|
|
|
from .base import BaseTranslator
|
|
|
|
|
|
class SmartTranslator(BaseTranslator):
|
|
def __init__(self, api_key: str | None = None, model: str = "gpt-4.1-mini", batch_size: int = 40):
|
|
api_key = api_key or os.getenv("OPENAI_API_KEY")
|
|
if not api_key:
|
|
raise ValueError("OPENAI_API_KEY mangler for smart mode")
|
|
|
|
self.client = OpenAI(api_key=api_key)
|
|
self.model = model
|
|
self.batch_size = batch_size
|
|
|
|
def _translate_batch(self, batch: List[str], source_lang: str, target_lang: str) -> List[str]:
|
|
payload = [{"i": i, "text": t} for i, t in enumerate(batch)]
|
|
|
|
prompt = (
|
|
f"Translate these subtitle lines from {source_lang} to {target_lang}.\n"
|
|
"Return ONLY valid JSON array.\n"
|
|
'Each item must be like: {"i": 0, "text": "..."}\n'
|
|
"Keep same order, keep line meaning natural and concise.\n\n"
|
|
f"{json.dumps(payload, ensure_ascii=False)}"
|
|
)
|
|
|
|
response = self.client.chat.completions.create(
|
|
model=self.model,
|
|
messages=[{"role": "user", "content": prompt}],
|
|
temperature=0.2,
|
|
)
|
|
|
|
text = response.choices[0].message.content or ""
|
|
|
|
try:
|
|
data = json.loads(text)
|
|
return [item["text"] for item in data]
|
|
except Exception:
|
|
return batch
|
|
|
|
def translate_blocks(
|
|
self,
|
|
texts: List[str],
|
|
source_lang: str = "auto",
|
|
target_lang: str = "da",
|
|
) -> List[str]:
|
|
out = []
|
|
|
|
for i in range(0, len(texts), self.batch_size):
|
|
batch = texts[i:i + self.batch_size]
|
|
out.extend(self._translate_batch(batch, source_lang, target_lang))
|
|
|
|
return out
|