# translator.py from gradio_client import Client import re import time import config import logging # 設定日誌 logger = logging.getLogger(__name__) try: # 💡 真正的 NLLB 運算大本營在這裡 client = Client("https://ai-labs.ilrdf.org.tw/kari-seejiq-tnpusu-ai-hmjil/") except Exception as e: logger.error(f"翻譯引擎初始化失敗: {e}") def get_clean_value(res): if isinstance(res, dict) and 'value' in res: return res['value'] if isinstance(res, list) and len(res) > 0: return res[0] return res def is_gibberish(text): """防亂碼濾網:檢查是否違反基本拼寫原則""" text_lower = text.lower() if re.search(r'[fvz]', text_lower): return True if re.search(r'[^aeiouwy\s]{6,}', text_lower): return True return False def calculate_confidence(text, is_chinese, tribe_name): """智慧信心值判定核心""" if not is_chinese and tribe_name == "太魯閣" and is_gibberish(text): return "low", "低 (疑為亂碼或不符拼寫規範)" if is_chinese and (len(set(text)) < 3 and len(text) > 6): return "low", "低 (語意不清或無效輸入)" complex_keywords = ["法律", "規定", "科技", "系統", "網路", "醫療", "政策", "分析", "資料", "會議", "機制", "科學", "專業", "名詞"] if is_chinese: if len(text) > 25 or any(kw in text for kw in complex_keywords): return "medium", "中 (含專業術語或複雜長句)" else: if len(text.split()) > 10: return "medium", "中 (複雜句結構)" return "high", "高 (一般生活簡單句)" def basic_format(text, direction): """💡 使用超快速的 Python 原生語法進行基本格式化""" text = str(text).strip() if direction == "zh_to_native" and text: # 確保輸出的族語第一個字母大寫 text = text[0].upper() + text[1:] return text def translate(text: str, tribe_name: str): # 💡 確保傳入資料庫的名稱是正確的,避免 RAG 抓空 db_tribe_name = "太魯閣語" if tribe_name == "太魯閣" else tribe_name if tribe_name not in config.TRIBE_MAP: return {"error": f"暫時不支援 {tribe_name}"} try: is_chinese = bool(re.search(r'[\u4e00-\u9fa5]', text)) # 計算信心值 conf_level, conf_desc = calculate_confidence(text, is_chinese, tribe_name) if conf_level == "low": return { "source": text, "target": "⚠️ 無法精準翻譯,請確認拼字或語意是否完整。", "direction": "unknown", "tribe": tribe_name, "db_tribe": db_tribe_name, "confidence_level": conf_level, "confidence_desc": conf_desc } # 💡 測速計時起點 api_start_time = time.time() # 正常翻譯流程 (純 NLLB,無 Gemini 負擔) if is_chinese: back_code = get_clean_value(client.predict(ethnicity=tribe_name, api_name="/lambda_1")) raw_result = get_clean_value(client.predict( text=text, src_lang="zho_Hant", tgt_lang=back_code, api_name="/translate_1" )) direction = "zh_to_native" final_result = basic_format(raw_result, direction) else: go_code = get_clean_value(client.predict(ethnicity=tribe_name, api_name="/lambda")) raw_result = get_clean_value(client.predict( text=text, src_lang=go_code, tgt_lang="zho_Hant", api_name="/translate" )) direction = "native_to_zh" final_result = basic_format(raw_result, direction) # 💡 測速計時終點 api_duration = time.time() - api_start_time logger.info(f"📡 [遠端 API 呼叫耗時] 字數: {len(text)} | 等待 AI Labs 伺服器回應耗時: {api_duration:.2f} 秒") return { "source": text, "target": final_result, "direction": direction, "tribe": tribe_name, "db_tribe": db_tribe_name, # 💡 提供給後續 deep_analyzer 進行 RAG 檢索使用 "confidence_level": conf_level, "confidence_desc": conf_desc } except Exception as e: logger.error(f"翻譯過程出錯: {e}") return {"error": f"翻譯過程出錯: {str(e)}"}