diff --git a/src-python/backend_test.py b/src-python/backend_test.py index 6f1de883..d56b1622 100644 --- a/src-python/backend_test.py +++ b/src-python/backend_test.py @@ -368,6 +368,7 @@ class TestMainloop(): if expected_status == [401]: print(f"-> {Color.YELLOW}[SKIP]{Color.RESET} No test available for this endpoint: {endpoint}.") self.record_test_result(endpoint, None, None, expected_status) # テスト結果を記録 + success=True return success elif expected_status == [404]: print(f"-> {Color.RED}[ERROR]{Color.RESET} Unknown endpoint: {endpoint}.") @@ -474,6 +475,7 @@ class TestMainloop(): if expected_status == [401]: print(f"-> {Color.YELLOW}[SKIP]{Color.RESET} No test available for this endpoint: {endpoint}.") self.record_test_result(endpoint, None, None, expected_status) # テスト結果を記録 + success=True return success elif expected_status == [404]: print(f"-> {Color.RED}[ERROR]{Color.RESET} Unknown endpoint: {endpoint}.") @@ -625,6 +627,70 @@ class TestMainloop(): self.test_delete_data_endpoints_single(endpoint) print("----データ削除系のエンドポイントのテスト終了----") + def test_translate_language(self, text): + """ + 指定された言語ペアで翻訳をテストする + :param text: 翻訳するテキスト + :return: 翻訳結果とステータスコード + """ + # エンドポイント + endpoint = "/run/send_message_box" + result, status = self.main.handleRequest(endpoint, text) + return result, status + + def test_translate_all_language_pairs(self): + results = {} + # 翻訳機能を有効にする + self.main.handleRequest("/set/enable/translation", None) + # 対応する言語コードのリストを取得 + self.config_dict["selectable_language_list"], _ = self.main.handleRequest("/get/data/selectable_language_list", None) + selectable_language_list = self.config_dict.get("selectable_language_list", None) + # すべての言語ペアで翻訳をテスト + for source_lang in selectable_language_list: + results[source_lang["language"]] = {} + for target_lang in selectable_language_list: + results[source_lang["language"]][target_lang["language"]] = {} + data = {} + for i in ["1", "2", "3"]: + data[i] = {} + data[i]["1"] = source_lang | {"enable": True} + self.main.handleRequest("/set/data/selected_your_languages", data) + data = {} + for i in ["1", "2", "3"]: + data[i] = {} + for j in ["1", "2", "3"]: + if j == "1": + data[i][j] = target_lang | {"enable": True} + else: + data[i][j] = target_lang | {"enable": False} + self.main.handleRequest("/set/data/selected_target_languages", data) + + # 翻訳エンジンを設定する(例: "CTranslate2") + self.config_dict["translation_engines"], _ = self.main.handleRequest("/get/data/translation_engines", None) + translation_engines = self.config_dict.get("translation_engines", None) + for engine in translation_engines: + results[source_lang["language"]][target_lang["language"]][engine] = None + data = {} + for i in ["1", "2", "3"]: + data[i] = engine + self.main.handleRequest("/set/data/selected_translation_engines", data) + + # テスト翻訳を実行 + print(f"Translating from {source_lang} to {target_lang} using {engine}") + result, status = self.test_translate_language({"id":"000001", "message":"こんにちわ 世界!"}) + if status == 200: + print(f"-> {Color.GREEN}[PASS]{Color.RESET} Translation from {source_lang} to {target_lang}: {result}") + results[source_lang["language"]][target_lang["language"]][engine] = True + else: + print(f"-> {Color.RED}[ERROR]{Color.RESET} Translation from {source_lang} to {target_lang} failed with status {status}") + results[source_lang["language"]][target_lang["language"]][engine] = False + # 翻訳機能を無効にする + self.main.handleRequest("/set/disable/translation", None) + print("----すべての言語ペアでの翻訳テスト終了----") + import json + with open("translation_test_results.json", "w", encoding="utf-8") as f: + json.dump(results, f, indent=4, ensure_ascii=False) + def generate_summary(self): """ テスト結果のサマリーを生成して表示する @@ -669,14 +735,15 @@ if __name__ == "__main__": import traceback try: test = TestMainloop() - test.test_endpoints_on_off_all() - test.test_set_data_endpoints_all() - test.test_run_endpoints_all() - test.test_delete_data_endpoints_all() - # test.test_endpoints_all_random() + # test.test_endpoints_on_off_all() + # test.test_set_data_endpoints_all() + # test.test_run_endpoints_all() + # test.test_delete_data_endpoints_all() + test.test_endpoints_all_random() # test.test_endpoints_on_off_continuous() # test.test_endpoints_on_off_random() # test.test_endpoints_specific_random() + # test.test_translate_all_language_pairs() test.generate_summary() except KeyboardInterrupt: print("Interrupted by user, shutting down...") diff --git a/src-python/controller.py b/src-python/controller.py index 4015016f..f40a25ae 100644 --- a/src-python/controller.py +++ b/src-python/controller.py @@ -1,3 +1,4 @@ +import copy from typing import Callable, Any from time import sleep from subprocess import Popen @@ -753,25 +754,10 @@ class Controller: def setSelectedTranslationComputeDevice(self, device:str, *args, **kwargs) -> dict: printLog("setSelectedTranslationComputeDevice", device) - pre_device = config.SELECTED_TRANSLATION_COMPUTE_DEVICE - pre_compute_type = config.SELECTED_TRANSLATION_COMPUTE_TYPE config.SELECTED_TRANSLATION_COMPUTE_DEVICE = device config.SELECTED_TRANSLATION_COMPUTE_TYPE = "auto" - try: - model.changeTranslatorCTranslate2Model() - self.run(200, self.run_mapping["selected_translation_compute_type"], config.SELECTED_TRANSLATION_COMPUTE_TYPE) - except Exception as e: - # VRAM不足エラーの検出(デバイス切り替え時) - is_vram_error, error_message = model.detectVRAMError(e) - if is_vram_error: - # 前のデバイス設定に戻す - printLog("VRAM error detected, reverting device setting") - config.SELECTED_TRANSLATION_COMPUTE_DEVICE = pre_device - config.SELECTED_TRANSLATION_COMPUTE_TYPE = pre_compute_type - model.changeTranslatorCTranslate2Model() - else: - # その他のエラーは通常通り処理 - errorLogging() + self.run(200, self.run_mapping["selected_translation_compute_type"], config.SELECTED_TRANSLATION_COMPUTE_TYPE) + model.setChangedTranslatorParameters(True) return {"status":200,"result":config.SELECTED_TRANSLATION_COMPUTE_DEVICE} @staticmethod @@ -801,12 +787,39 @@ class Controller: # def getMaxSpeakerThreshold(*args, **kwargs) -> dict: # return {"status":200, "result":config.MAX_SPEAKER_THRESHOLD} - @staticmethod - def setEnableTranslation(*args, **kwargs) -> dict: + def setEnableTranslation(self, *args, **kwargs) -> dict: if config.ENABLE_TRANSLATION is False: - if model.isLoadedCTranslate2Model() is False: - model.changeTranslatorCTranslate2Model() - config.ENABLE_TRANSLATION = True + if model.isLoadedCTranslate2Model() is False or model.isChangedTranslatorParameters() is True: + try: + model.changeTranslatorCTranslate2Model() + model.setChangedTranslatorParameters(False) + config.ENABLE_TRANSLATION = True + except Exception as e: + # VRAM不足エラーの検出(デバイス切り替え時) + is_vram_error, error_message = model.detectVRAMError(e) + if is_vram_error: + # Defaultのデバイス設定に戻す + printLog("VRAM error detected, reverting device setting") + self.setDisableTranslation() + config.SELECTED_TRANSLATION_COMPUTE_DEVICE = copy.deepcopy(config.SELECTABLE_COMPUTE_DEVICE_LIST[0]) + config.SELECTED_TRANSLATION_COMPUTE_TYPE = "auto" + self.run(200, self.run_mapping["selected_translation_compute_device"], config.SELECTED_TRANSLATION_COMPUTE_DEVICE) + self.run(200, self.run_mapping["selected_translation_compute_type"], config.SELECTED_TRANSLATION_COMPUTE_TYPE) + self.run( + 400, + self.run_mapping["enable_translation"], + { + "message":"Translation disabled due to VRAM overflow", + "data": False + }, + ) + model.changeTranslatorCTranslate2Model() + model.setChangedTranslatorParameters(False) + else: + # その他のエラーは通常通り処理 + errorLogging() + else: + config.ENABLE_TRANSLATION = True return {"status":200, "result":config.ENABLE_TRANSLATION} @staticmethod @@ -1571,17 +1584,8 @@ class Controller: @staticmethod def setCtranslate2WeightType(data, *args, **kwargs) -> dict: - pre_weight_type = config.CTRANSLATE2_WEIGHT_TYPE config.CTRANSLATE2_WEIGHT_TYPE = str(data) - if model.checkTranslatorCTranslate2ModelWeight(config.CTRANSLATE2_WEIGHT_TYPE): - def callback(): - model.changeTranslatorCTranslate2Model() - th_callback = Thread(target=callback) - th_callback.daemon = True - th_callback.start() - th_callback.join() - else: - config.CTRANSLATE2_WEIGHT_TYPE = pre_weight_type + model.setChangedTranslatorParameters(True) return {"status":200, "result":config.CTRANSLATE2_WEIGHT_TYPE} @staticmethod @@ -1590,17 +1594,8 @@ class Controller: @staticmethod def setSelectedTranslationComputeType(data, *args, **kwargs) -> dict: - pre_compute_type = config.SELECTED_TRANSLATION_COMPUTE_TYPE config.SELECTED_TRANSLATION_COMPUTE_TYPE = str(data) - if model.checkTranslatorCTranslate2ModelWeight(config.CTRANSLATE2_WEIGHT_TYPE): - def callback(): - model.changeTranslatorCTranslate2Model() - th_callback = Thread(target=callback) - th_callback.daemon = True - th_callback.start() - th_callback.join() - else: - config.SELECTED_TRANSLATION_COMPUTE_TYPE = pre_compute_type + model.setChangedTranslatorParameters(True) return {"status":200, "result":config.SELECTED_TRANSLATION_COMPUTE_TYPE} @staticmethod diff --git a/src-python/model.py b/src-python/model.py index 6048c630..bbf43604 100644 --- a/src-python/model.py +++ b/src-python/model.py @@ -128,6 +128,12 @@ class Model: def isLoadedCTranslate2Model(self): return self.translator.isLoadedCTranslate2Model() + def isChangedTranslatorParameters(self): + return self.translator.isChangedTranslatorParameters() + + def setChangedTranslatorParameters(self, is_changed): + self.translator.setChangedTranslatorParameters(is_changed) + def checkTranscriptionWhisperModelWeight(self, weight_type:str): return checkWhisperWeight(config.PATH_LOCAL, weight_type) diff --git a/src-python/models/translation/translation_languages.py b/src-python/models/translation/translation_languages.py index a697960b..2a660e17 100644 --- a/src-python/models/translation/translation_languages.py +++ b/src-python/models/translation/translation_languages.py @@ -176,7 +176,7 @@ dict_google_languages = { "Belarusian":"be", "Cebuano":"ceb", "Esperanto":"eo", - "Basque":"eu", + # "Basque":"eu", "Irish":"ga" } translation_lang["Google"] = { @@ -317,7 +317,7 @@ dict_ctranslate2_languages = { "Malayalam": "ml", "Welsh": "cy", "Slovak": "sk", - "Telugu": "te", + # "Telugu": "te", "Persian": "fa", "Latvian": "lv", "Bengali": "bn", @@ -328,7 +328,7 @@ dict_ctranslate2_languages = { "Estonian": "et", "Macedonian": "mk", "Breton": "br", - "Basque": "eu", + # "Basque": "eu", "Icelandic": "is", "Armenian": "hy", "Nepali": "ne", diff --git a/src-python/models/translation/translation_translator.py b/src-python/models/translation/translation_translator.py index a9a1a56a..a12b326e 100644 --- a/src-python/models/translation/translation_translator.py +++ b/src-python/models/translation/translation_translator.py @@ -23,6 +23,7 @@ class Translator(): self.ctranslate2_translator = None self.ctranslate2_tokenizer = None self.is_loaded_ctranslate2_model = False + self.is_changed_translator_parameters = False self.is_enable_translators = ENABLE_TRANSLATORS def authenticationDeepLAuthKey(self, authkey): @@ -64,6 +65,12 @@ class Translator(): def isLoadedCTranslate2Model(self): return self.is_loaded_ctranslate2_model + def isChangedTranslatorParameters(self): + return self.is_changed_translator_parameters + + def setChangedTranslatorParameters(self, is_changed): + self.is_changed_translator_parameters = is_changed + def translateCTranslate2(self, message, source_language, target_language): result = False if self.is_loaded_ctranslate2_model is True: diff --git a/src-ui/app/_app_controllers/ConfigPageCloseTriggerController.jsx b/src-ui/app/_app_controllers/ConfigPageCloseTriggerController.jsx index c04e2a1a..3a39be58 100644 --- a/src-ui/app/_app_controllers/ConfigPageCloseTriggerController.jsx +++ b/src-ui/app/_app_controllers/ConfigPageCloseTriggerController.jsx @@ -15,8 +15,14 @@ import { useStore_MainFunctionsStateMemory } from "@store"; export const ConfigPageCloseTriggerController = () => { const { currentIsOpenedConfigPage } = useIsOpenedConfigPage(); - const { currentMainFunctionsStateMemory, updateMainFunctionsStateMemory} = useStore_MainFunctionsStateMemory(); const { + currentMainFunctionsStateMemory, + updateMainFunctionsStateMemory, + } = useStore_MainFunctionsStateMemory(); + + const { + currentTranslationStatus, + setTranslation, currentTranscriptionSendStatus, setTranscriptionSend, currentTranscriptionReceiveStatus, @@ -34,12 +40,14 @@ export const ConfigPageCloseTriggerController = () => { const memorizeLatestMainFunctionsState = () => { updateMainFunctionsStateMemory({ + translation: currentTranslationStatus.data, transcription_send: currentTranscriptionSendStatus.data, transcription_receive: currentTranscriptionReceiveStatus.data, }); }; const restoreMainFunctionState = () => { + if (currentMainFunctionsStateMemory.data.translation === true) setTranslation(true); if (currentMainFunctionsStateMemory.data.transcription_send === true) setTranscriptionSend(true); if (currentMainFunctionsStateMemory.data.transcription_receive === true) setTranscriptionReceive(true); }; @@ -48,6 +56,7 @@ export const ConfigPageCloseTriggerController = () => { if (currentIsOpenedConfigPage.data === true) { // When config page is opened. memorizeLatestMainFunctionsState(); unregisterAll(); + if (currentTranslationStatus.data === true) setTranslation(false); if (currentTranscriptionSendStatus.data === true) setTranscriptionSend(false); if (currentTranscriptionReceiveStatus.data === true) setTranscriptionReceive(false); } else if (currentIsOpenedConfigPage.data === false) { // When config page is closed.