from typing import Dict, Any, Optional from aliyunsdkcore.client import AcsClient from aliyunsdkalimt.request.v20181012 import TranslateGeneralRequest, TranslateECommerceRequest from app.services.translation_quota import TranslationQuotaService from app.database import AsyncSessionLocal import asyncio import json import logging logger = logging.getLogger(__name__) ALIBABA_LANG_MAP = { "zh": "zh", "en": "en", "ja": "ja", "ko": "ko", "fr": "fr", "de": "de", "es": "es", "pt": "pt", "ru": "ru", "ar": "ar", "th": "th", "vi": "vi", "id": "id", "ms": "ms", "tl": "tl", "hi": "hi", } class AlibabaMTProvider: def __init__(self, access_key_id: str, access_key_secret: str, region_id: str = "cn-hangzhou"): self.client = AcsClient(access_key_id, access_key_secret, region_id) self._name = "alibaba-mt" async def translate(self, text: str, source_lang: Optional[str], target_lang: str, context: Optional[str] = None) -> Dict[str, Any]: src = source_lang if source_lang and source_lang != "auto" else "auto" tgt = ALIBABA_LANG_MAP.get(target_lang[:2].lower(), "en") async with AsyncSessionLocal() as db: quota_svc = TranslationQuotaService(db) for version in ("ecommerce", "general"): if not await quota_svc.check_quota(version): logger.info(f"Quota [{version}] exhausted or disabled, trying next") continue result = await self._do_translate(version, text, src, tgt) if result and result.get("translated_text"): await quota_svc.consume(version, len(text)) await db.commit() result["provider"] = f"{self.name}-{version}" return result raise Exception("Alibaba MT: both versions quota exhausted or API failed") async def _do_translate(self, version: str, text: str, src: str, tgt: str) -> Optional[Dict[str, Any]]: try: if version == "ecommerce": req = TranslateECommerceRequest.TranslateECommerceRequest() else: req = TranslateGeneralRequest.TranslateGeneralRequest() req.set_FormatType("text") req.set_Scene(version) req.set_SourceLanguage(src) req.set_TargetLanguage(tgt) req.set_SourceText(text) loop = asyncio.get_event_loop() body = await loop.run_in_executor(None, self.client.do_action_with_exception, req) resp = json.loads(body) data = resp.get("Data", {}) translated = data.get("Translated", "") detected = data.get("DetectedLanguage", src) if translated: logger.info(f"Alibaba MT [{version}] ok: {len(text)} chars translated") return { "translated_text": translated, "provider": f"{self.name}-{version}", "detected_source_lang": detected, "char_count": len(text), "cost": 0, } except Exception as e: logger.warning(f"Alibaba MT [{version}] failed: {e}") return None async def reply(self, *args, **kwargs) -> Dict[str, Any]: raise NotImplementedError("Alibaba MT does not support reply generation") async def generate_marketing(self, *args, **kwargs) -> Dict[str, Any]: raise NotImplementedError("Alibaba MT does not support marketing generation") async def extract_info(self, text: str, schema: Dict[str, Any]) -> Dict[str, Any]: raise NotImplementedError("Alibaba MT does not support info extraction") @property def name(self) -> str: return self._name @property def cost_per_1k_tokens(self) -> float: return 0