翻訳バックエンドを拡張・リファクタリング:OpenAI/Plamo/Gemini クライアントを追加・改修し、プロンプトを YAML から読み込むように変更。各クライアントでモデル一覧取得・認証・クライアント更新機能を実装し、Translator/Model 層の対応メソッドを追加。Controller と mainloop にプラモ・ジェミニ・OpenAI の認証/モデル操作エンドポイントを追加・整備。config のモデル/API設定をプロパティ化して既定値を None に変更し、選択肢リストを初期化。translation_languages に OpenAI 用マッピングを追加。requirements ファイルの依存記述を調整。

This commit is contained in:
misyaguziya
2025-10-16 18:09:08 +09:00
parent f8466bd6e4
commit 526fd4d5aa
13 changed files with 842 additions and 337 deletions

View File

@@ -20,6 +20,8 @@ hf-xet==1.1.2
setuptools==80.8.0 setuptools==80.8.0
langchain-openai==0.3.32 langchain-openai==0.3.32
langchain-google-genai==2.1.10 langchain-google-genai==2.1.10
google-genai==1.45.0
grpcio==1.67.1
SudachiPy==0.6.10 SudachiPy==0.6.10
SudachiDict-core==20250825 SudachiDict-core==20250825
SudachiDict-full==20250825 SudachiDict-full==20250825

View File

@@ -21,6 +21,8 @@ hf-xet==1.1.2
setuptools==80.8.0 setuptools==80.8.0
langchain-openai==0.3.32 langchain-openai==0.3.32
langchain-google-genai==2.1.10 langchain-google-genai==2.1.10
google-genai==1.45.0
grpcio==1.67.1
SudachiPy==0.6.10 SudachiPy==0.6.10
SudachiDict-core==20250825 SudachiDict-core==20250825
SudachiDict-full==20250825 SudachiDict-full==20250825

View File

@@ -35,16 +35,6 @@ try:
except Exception: # pragma: no cover - optional runtime except Exception: # pragma: no cover - optional runtime
whisper_models = {} # type: ignore whisper_models = {} # type: ignore
try:
from models.translation.translation_gemini import _MODELS as gemini_models
except Exception: # pragma: no cover - optional runtime
gemini_models = [] # type: ignore
try:
from models.translation.translation_plamo import _MODELS as plamo_models
except Exception: # pragma: no cover - optional runtime
plamo_models = [] # type: ignore
from utils import errorLogging, validateDictStructure, getComputeDeviceList from utils import errorLogging, validateDictStructure, getComputeDeviceList
json_serializable_vars = {} json_serializable_vars = {}
@@ -173,14 +163,6 @@ class Config:
def SELECTABLE_TRANSLATION_ENGINE_LIST(self): def SELECTABLE_TRANSLATION_ENGINE_LIST(self):
return self._SELECTABLE_TRANSLATION_ENGINE_LIST return self._SELECTABLE_TRANSLATION_ENGINE_LIST
@property
def SELECTABLE_PLAMO_MODEL_LIST(self):
return self._SELECTABLE_PLAMO_MODEL_LIST
@property
def SELECTABLE_GEMINI_MODEL_LIST(self):
return self._SELECTABLE_GEMINI_MODEL_LIST
@property @property
def SELECTABLE_TRANSCRIPTION_ENGINE_LIST(self): def SELECTABLE_TRANSCRIPTION_ENGINE_LIST(self):
return self._SELECTABLE_TRANSCRIPTION_ENGINE_LIST return self._SELECTABLE_TRANSCRIPTION_ENGINE_LIST
@@ -329,6 +311,33 @@ class Config:
if isinstance(value, dict): if isinstance(value, dict):
self._SELECTABLE_TRANSCRIPTION_ENGINE_STATUS = value self._SELECTABLE_TRANSCRIPTION_ENGINE_STATUS = value
@property
def SELECTABLE_PLAMO_MODEL_LIST(self):
return self._SELECTABLE_PLAMO_MODEL_LIST
@SELECTABLE_PLAMO_MODEL_LIST.setter
def SELECTABLE_PLAMO_MODEL_LIST(self, value):
if isinstance(value, list):
self._SELECTABLE_PLAMO_MODEL_LIST = value
@property
def SELECTABLE_GEMINI_MODEL_LIST(self):
return self._SELECTABLE_GEMINI_MODEL_LIST
@SELECTABLE_GEMINI_MODEL_LIST.setter
def SELECTABLE_GEMINI_MODEL_LIST(self, value):
if isinstance(value, list):
self._SELECTABLE_GEMINI_MODEL_LIST = value
@property
def SELECTABLE_OPENAI_MODEL_LIST(self):
return self._SELECTABLE_OPENAI_MODEL_LIST
@SELECTABLE_OPENAI_MODEL_LIST.setter
def SELECTABLE_OPENAI_MODEL_LIST(self, value):
if isinstance(value, list):
self._SELECTABLE_OPENAI_MODEL_LIST = value
# Save Json Data # Save Json Data
## Main Window ## Main Window
@property @property
@@ -936,6 +945,18 @@ class Config:
self._GEMINI_MODEL = value self._GEMINI_MODEL = value
self.saveConfig(inspect.currentframe().f_code.co_name, value) self.saveConfig(inspect.currentframe().f_code.co_name, value)
@property
@json_serializable('OPENAI_MODEL')
def OPENAI_MODEL(self):
return self._OPENAI_MODEL
@OPENAI_MODEL.setter
def OPENAI_MODEL(self, value):
if isinstance(value, str):
if value in self.SELECTABLE_OPENAI_MODEL_LIST:
self._OPENAI_MODEL = value
self.saveConfig(inspect.currentframe().f_code.co_name, value)
@property @property
@json_serializable('AUTO_CLEAR_MESSAGE_BOX') @json_serializable('AUTO_CLEAR_MESSAGE_BOX')
def AUTO_CLEAR_MESSAGE_BOX(self): def AUTO_CLEAR_MESSAGE_BOX(self):
@@ -1160,8 +1181,9 @@ class Config:
self._SELECTABLE_TRANSCRIPTION_ENGINE_LIST = list(transcription_lang[first_key].values())[0].keys() self._SELECTABLE_TRANSCRIPTION_ENGINE_LIST = list(transcription_lang[first_key].values())[0].keys()
except Exception: except Exception:
self._SELECTABLE_TRANSCRIPTION_ENGINE_LIST = [] self._SELECTABLE_TRANSCRIPTION_ENGINE_LIST = []
self._SELECTABLE_PLAMO_MODEL_LIST = plamo_models self._SELECTABLE_PLAMO_MODEL_LIST = []
self._SELECTABLE_GEMINI_MODEL_LIST = gemini_models self._SELECTABLE_GEMINI_MODEL_LIST = []
self._SELECTABLE_OPENAI_MODEL_LIST = []
self._SELECTABLE_UI_LANGUAGE_LIST = ["en", "ja", "ko", "zh-Hant", "zh-Hans"] self._SELECTABLE_UI_LANGUAGE_LIST = ["en", "ja", "ko", "zh-Hant", "zh-Hans"]
self._COMPUTE_MODE = "cuda" if torch.cuda.is_available() else "cpu" self._COMPUTE_MODE = "cuda" if torch.cuda.is_available() else "cpu"
self._SELECTABLE_COMPUTE_DEVICE_LIST = getComputeDeviceList() self._SELECTABLE_COMPUTE_DEVICE_LIST = getComputeDeviceList()
@@ -1313,13 +1335,15 @@ class Config:
"DeepL_API": None, "DeepL_API": None,
"Plamo_API": None, "Plamo_API": None,
"Gemini_API": None, "Gemini_API": None,
"OpenAI_API": None,
} }
self._USE_EXCLUDE_WORDS = True self._USE_EXCLUDE_WORDS = True
self._SELECTED_TRANSLATION_COMPUTE_DEVICE = copy.deepcopy(self.SELECTABLE_COMPUTE_DEVICE_LIST[0]) self._SELECTED_TRANSLATION_COMPUTE_DEVICE = copy.deepcopy(self.SELECTABLE_COMPUTE_DEVICE_LIST[0])
self._SELECTED_TRANSCRIPTION_COMPUTE_DEVICE = copy.deepcopy(self.SELECTABLE_COMPUTE_DEVICE_LIST[0]) self._SELECTED_TRANSCRIPTION_COMPUTE_DEVICE = copy.deepcopy(self.SELECTABLE_COMPUTE_DEVICE_LIST[0])
self._CTRANSLATE2_WEIGHT_TYPE = "m2m100_418M-ct2-int8" self._CTRANSLATE2_WEIGHT_TYPE = "m2m100_418M-ct2-int8"
self._PLAMO_MODEL = "plamo-2.0-prime" self._PLAMO_MODEL = None
self._GEMINI_MODEL = "gemini-2.5-flash-lite" self._GEMINI_MODEL = None
self._OPENAI_MODEL = None
self._SELECTED_TRANSLATION_COMPUTE_TYPE = "auto" self._SELECTED_TRANSLATION_COMPUTE_TYPE = "auto"
self._WHISPER_WEIGHT_TYPE = "base" self._WHISPER_WEIGHT_TYPE = "base"
self._SELECTED_TRANSCRIPTION_COMPUTE_TYPE = "auto" self._SELECTED_TRANSCRIPTION_COMPUTE_TYPE = "auto"

View File

@@ -1605,36 +1605,6 @@ class Controller:
self.updateTranslationEngineAndEngineList() self.updateTranslationEngineAndEngineList()
return {"status":200, "result":config.AUTH_KEYS[translator_name]} return {"status":200, "result":config.AUTH_KEYS[translator_name]}
def getPlamoModelList(self, *args, **kwargs) -> dict:
return {"status":200, "result": config.SELECTABLE_PLAMO_MODEL_LIST}
def setPlamoModel(self, data, *args, **kwargs) -> dict:
printLog("Set Plamo Model", data)
try:
data = str(data)
result = model.authenticationTranslatorPlamoAuthKey(auth_key=config.AUTH_KEYS["Plamo_API"], model_name=data)
if result is True:
config.PLAMO_MODEL = data
response = {"status":200, "result":config.PLAMO_MODEL}
else:
response = {
"status":400,
"result":{
"message":"Plamo model is not valid",
"data": config.PLAMO_MODEL
}
}
except Exception as e:
errorLogging()
response = {
"status":400,
"result":{
"message":f"Error {e}",
"data": config.PLAMO_MODEL
}
}
return response
def getPlamoAuthKey(self, *args, **kwargs) -> dict: def getPlamoAuthKey(self, *args, **kwargs) -> dict:
return {"status":200, "result":config.AUTH_KEYS["Plamo_API"]} return {"status":200, "result":config.AUTH_KEYS["Plamo_API"]}
@@ -1644,13 +1614,19 @@ class Controller:
try: try:
data = str(data) data = str(data)
if len(data) == 72: if len(data) == 72:
result = model.authenticationTranslatorPlamoAuthKey(auth_key=data, model_name=config.PLAMO_MODEL) result = model.authenticationTranslatorPlamoAuthKey(auth_key=data)
if result is True: if result is True:
key = data key = data
auth_keys = config.AUTH_KEYS auth_keys = config.AUTH_KEYS
auth_keys[translator_name] = key auth_keys[translator_name] = key
config.AUTH_KEYS = auth_keys config.AUTH_KEYS = auth_keys
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[translator_name] = True config.SELECTABLE_TRANSLATION_ENGINE_STATUS[translator_name] = True
config.SELECTABLE_PLAMO_MODEL_LIST = model.getTranslatorPlamoModelList()
# ここにrunが必要
if config.PLAMO_MODEL not in config.SELECTABLE_PLAMO_MODEL_LIST:
config.PLAMO_MODEL = config.SELECTABLE_PLAMO_MODEL_LIST[0]
# ここにrunが必要
model.updateTranslatorPlamoClient()
self.updateTranslationEngineAndEngineList() self.updateTranslationEngineAndEngineList()
response = {"status":200, "result":config.AUTH_KEYS[translator_name]} response = {"status":200, "result":config.AUTH_KEYS[translator_name]}
else: else:
@@ -1689,23 +1665,27 @@ class Controller:
self.updateTranslationEngineAndEngineList() self.updateTranslationEngineAndEngineList()
return {"status":200, "result":config.AUTH_KEYS[translator_name]} return {"status":200, "result":config.AUTH_KEYS[translator_name]}
def getGeminiModelList(self, *args, **kwargs) -> dict: def getPlamoModelList(self, *args, **kwargs) -> dict:
return {"status":200, "result": config.SELECTABLE_GEMINI_MODEL_LIST} return {"status":200, "result": config.SELECTABLE_PLAMO_MODEL_LIST}
def setGeminiModel(self, data, *args, **kwargs) -> dict: def getPlamoModel(self, *args, **kwargs) -> dict:
printLog("Set Gemini Model", data) return {"status":200, "result":config.PLAMO_MODEL}
def setPlamoModel(self, data, *args, **kwargs) -> dict:
printLog("Set Plamo Model", data)
try: try:
data = str(data) data = str(data)
result = model.authenticationTranslatorGeminiAuthKey(auth_key=config.AUTH_KEYS["Gemini_API"], model_name=data) result = model.setTranslatorPlamoModel(model=data)
if result is True: if result is True:
config.GEMINI_MODEL = data config.PLAMO_MODEL = data
response = {"status":200, "result":config.GEMINI_MODEL} model.updateTranslatorPlamoClient()
response = {"status":200, "result":config.PLAMO_MODEL}
else: else:
response = { response = {
"status":400, "status":400,
"result":{ "result":{
"message":"Gemini model is not valid", "message":"Plamo model is not valid",
"data": config.GEMINI_MODEL "data": config.PLAMO_MODEL
} }
} }
except Exception as e: except Exception as e:
@@ -1714,7 +1694,7 @@ class Controller:
"status":400, "status":400,
"result":{ "result":{
"message":f"Error {e}", "message":f"Error {e}",
"data": config.GEMINI_MODEL "data": config.PLAMO_MODEL
} }
} }
return response return response
@@ -1728,13 +1708,19 @@ class Controller:
try: try:
data = str(data) data = str(data)
if len(data) >= 20: if len(data) >= 20:
result = model.authenticationTranslatorGeminiAuthKey(auth_key=data, model_name=config.GEMINI_MODEL) result = model.authenticationTranslatorGeminiAuthKey(auth_key=data)
if result is True: if result is True:
key = data key = data
auth_keys = config.AUTH_KEYS auth_keys = config.AUTH_KEYS
auth_keys[translator_name] = key auth_keys[translator_name] = key
config.AUTH_KEYS = auth_keys config.AUTH_KEYS = auth_keys
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[translator_name] = True config.SELECTABLE_TRANSLATION_ENGINE_STATUS[translator_name] = True
config.SELECTABLE_GEMINI_MODEL_LIST = model.getTranslatorGeminiModelList()
# ここにrunが必要
if config.GEMINI_MODEL not in config.SELECTABLE_GEMINI_MODEL_LIST:
config.GEMINI_MODEL = config.SELECTABLE_GEMINI_MODEL_LIST[0]
# ここにrunが必要
model.updateTranslatorGeminiClient()
self.updateTranslationEngineAndEngineList() self.updateTranslationEngineAndEngineList()
response = {"status":200, "result":config.AUTH_KEYS[translator_name]} response = {"status":200, "result":config.AUTH_KEYS[translator_name]}
else: else:
@@ -1773,6 +1759,118 @@ class Controller:
self.updateTranslationEngineAndEngineList() self.updateTranslationEngineAndEngineList()
return {"status":200, "result":config.AUTH_KEYS[translator_name]} return {"status":200, "result":config.AUTH_KEYS[translator_name]}
def getGeminiModelList(self, *args, **kwargs) -> dict:
return {"status":200, "result": config.SELECTABLE_GEMINI_MODEL_LIST}
def getGeminiModel(self, *args, **kwargs) -> dict:
return {"status":200, "result":config.GEMINI_MODEL}
def setGeminiModel(self, data, *args, **kwargs) -> dict:
printLog("Set Gemini Model", data)
try:
data = str(data)
result = model.setTranslatorGeminiModel(model=data)
if result is True:
config.GEMINI_MODEL = data
model.updateTranslatorGeminiClient()
response = {"status":200, "result":config.GEMINI_MODEL}
else:
response = {
"status":400,
"result":{
"message":"Gemini model is not valid",
"data": config.GEMINI_MODEL
}
}
except Exception as e:
errorLogging()
response = {
"status":400,
"result":{
"message":f"Error {e}",
"data": config.GEMINI_MODEL
}
}
return response
@staticmethod
def getOpenAiAuthKey(*args, **kwargs) -> dict:
return {"status":200, "result":config.AUTH_KEYS["OpenAI_API"]}
def setOpenAiAuthKey(self, data, *args, **kwargs) -> dict:
printLog("Set OpenAI Auth Key", data)
translator_name = "OpenAI_API"
try:
data = str(data)
if len(data) >= 20:
key = data
auth_keys = config.AUTH_KEYS
auth_keys[translator_name] = key
config.AUTH_KEYS = auth_keys
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[translator_name] = True
self.updateTranslationEngineAndEngineList()
response = {"status":200, "result":config.AUTH_KEYS[translator_name]}
else:
response = {
"status":400,
"result":{
"message":"OpenAI auth key length is not correct",
"data": config.AUTH_KEYS[translator_name]
}
}
except Exception as e:
errorLogging()
response = {
"status":400,
"result":{
"message":f"Error {e}",
"data": config.AUTH_KEYS[translator_name]
}
}
return response
def delOpenAiAuthKey(self, *args, **kwargs) -> dict:
translator_name = "OpenAI_API"
auth_keys = config.AUTH_KEYS
auth_keys[translator_name] = None
config.AUTH_KEYS = auth_keys
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[translator_name] = False
self.updateTranslationEngineAndEngineList()
return {"status":200, "result":config.AUTH_KEYS[translator_name]}
def getOpenAiModelList(self, *args, **kwargs) -> dict:
return {"status":200, "result": config.SELECTABLE_OPENAI_MODEL_LIST}
def getOpenAiModel(self, *args, **kwargs) -> dict:
return {"status":200, "result":config.OPENAI_MODEL}
def setOpenAiModel(self, data, *args, **kwargs) -> dict:
printLog("Set OpenAI Model", data)
try:
data = str(data)
result = model.setTranslatorOpenAiModel(model=data)
if result is True:
config.OPENAI_MODEL = data
response = {"status":200, "result":config.OPENAI_MODEL}
else:
response = {
"status":400,
"result":{
"message":"OpenAI model is not valid",
"data": config.OPENAI_MODEL
}
}
except Exception as e:
errorLogging()
response = {
"status":400,
"result":{
"message":f"Error {e}",
"data": config.OPENAI_MODEL
}
}
return response
@staticmethod @staticmethod
def getCtranslate2WeightType(*args, **kwargs) -> dict: def getCtranslate2WeightType(*args, **kwargs) -> dict:
return {"status":200, "result":config.CTRANSLATE2_WEIGHT_TYPE} return {"status":200, "result":config.CTRANSLATE2_WEIGHT_TYPE}
@@ -2651,9 +2749,14 @@ class Controller:
printLog("Start check Plamo API Key") printLog("Start check Plamo API Key")
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False
if config.AUTH_KEYS[engine] is not None: if config.AUTH_KEYS[engine] is not None:
if model.authenticationTranslatorPlamoAuthKey(auth_key=config.AUTH_KEYS[engine], model=config.PLAMO_MODEL) is True: if model.authenticationTranslatorPlamoAuthKey(auth_key=config.AUTH_KEYS[engine]) is True:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True
printLog("Plamo API Key is valid") printLog("Plamo API Key is valid")
config.SELECTABLE_PLAMO_MODEL_LIST = model.getTranslatorPlamoModelList()
if config.PLAMO_MODEL not in config.SELECTABLE_PLAMO_MODEL_LIST:
config.PLAMO_MODEL = config.SELECTABLE_PLAMO_MODEL_LIST[0]
model.setTranslatorPlamoModel(config.PLAMO_MODEL)
model.updateTranslatorPlamoClient()
else: else:
# error update Auth key # error update Auth key
auth_keys = config.AUTH_KEYS auth_keys = config.AUTH_KEYS
@@ -2664,15 +2767,38 @@ class Controller:
printLog("Start check Gemini API Key") printLog("Start check Gemini API Key")
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False
if config.AUTH_KEYS[engine] is not None: if config.AUTH_KEYS[engine] is not None:
if model.authenticationTranslatorGeminiAuthKey(auth_key=config.AUTH_KEYS[engine], model=config.GEMINI_MODEL) is True: if model.authenticationTranslatorGeminiAuthKey(auth_key=config.AUTH_KEYS[engine]) is True:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True
printLog("Gemini API Key is valid") printLog("Gemini API Key is valid")
config.SELECTABLE_GEMINI_MODEL_LIST = model.getTranslatorGeminiModelList()
if config.GEMINI_MODEL not in config.SELECTABLE_GEMINI_MODEL_LIST:
config.GEMINI_MODEL = config.SELECTABLE_GEMINI_MODEL_LIST[0]
model.setTranslatorGeminiModel(config.GEMINI_MODEL)
model.updateTranslatorGeminiClient()
else: else:
# error update Auth key # error update Auth key
auth_keys = config.AUTH_KEYS auth_keys = config.AUTH_KEYS
auth_keys[engine] = None auth_keys[engine] = None
config.AUTH_KEYS = auth_keys config.AUTH_KEYS = auth_keys
printLog("Gemini API Key is invalid") printLog("Gemini API Key is invalid")
case "OpenAI_API":
printLog("Start check OpenAI API Key")
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False
if config.AUTH_KEYS[engine] is not None:
if model.authenticationTranslatorOpenAIAuthKey(auth_key=config.AUTH_KEYS[engine]) is True:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True
printLog("OpenAI API Key is valid")
config.SELECTABLE_OPENAI_MODEL_LIST = model.getTranslatorOpenAIModelList()
if config.OPENAI_MODEL not in config.SELECTABLE_OPENAI_MODEL_LIST:
config.OPENAI_MODEL = config.SELECTABLE_OPENAI_MODEL_LIST[0]
model.setTranslatorOpenAiModel(config.OPENAI_MODEL)
model.updateTranslatorOpenAIClient()
else:
# error update Auth key
auth_keys = config.AUTH_KEYS
auth_keys[engine] = None
config.AUTH_KEYS = auth_keys
printLog("OpenAI API Key is invalid")
case _: case _:
if connected_network is True: if connected_network is True:
config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True

View File

@@ -175,17 +175,26 @@ mapping = {
"/delete/data/deepl_auth_key": {"status": False, "variable":controller.delDeeplAuthKey}, "/delete/data/deepl_auth_key": {"status": False, "variable":controller.delDeeplAuthKey},
"/get/data/plamo_model_list": {"status": False, "variable":controller.getPlamoModelList}, "/get/data/plamo_model_list": {"status": False, "variable":controller.getPlamoModelList},
"/get/data/plamo_model": {"status": False, "variable":controller.getPlamoModel},
"/set/data/plamo_model": {"status": False, "variable":controller.setPlamoModel}, "/set/data/plamo_model": {"status": False, "variable":controller.setPlamoModel},
"/get/data/plamo_auth_key": {"status": False, "variable":controller.getPlamoAuthKey}, "/get/data/plamo_auth_key": {"status": False, "variable":controller.getPlamoAuthKey},
"/set/data/plamo_auth_key": {"status": False, "variable":controller.setPlamoAuthKey}, "/set/data/plamo_auth_key": {"status": False, "variable":controller.setPlamoAuthKey},
"/delete/data/plamo_auth_key": {"status": False, "variable":controller.delPlamoAuthKey}, "/delete/data/plamo_auth_key": {"status": False, "variable":controller.delPlamoAuthKey},
"/get/data/gemini_model_list": {"status": True, "variable":controller.getGeminiModelList}, "/get/data/gemini_model_list": {"status": True, "variable":controller.getGeminiModelList},
"/get/data/gemini_model": {"status": True, "variable":controller.getGeminiModel},
"/set/data/gemini_model": {"status": True, "variable":controller.setGeminiModel}, "/set/data/gemini_model": {"status": True, "variable":controller.setGeminiModel},
"/get/data/gemini_auth_key": {"status": True, "variable":controller.getGeminiAuthKey}, "/get/data/gemini_auth_key": {"status": True, "variable":controller.getGeminiAuthKey},
"/set/data/gemini_auth_key": {"status": True, "variable":controller.setGeminiAuthKey}, "/set/data/gemini_auth_key": {"status": True, "variable":controller.setGeminiAuthKey},
"/delete/data/gemini_auth_key": {"status": True, "variable":controller.delGeminiAuthKey}, "/delete/data/gemini_auth_key": {"status": True, "variable":controller.delGeminiAuthKey},
"/get/data/openai_model_list": {"status": True, "variable":controller.getOpenAiModelList},
"/get/data/openai_model": {"status": True, "variable":controller.getOpenAiModel},
"/set/data/openai_model": {"status": True, "variable":controller.setOpenAiModel},
"/get/data/openai_auth_key": {"status": True, "variable":controller.getOpenAiAuthKey},
"/set/data/openai_auth_key": {"status": True, "variable":controller.setOpenAiAuthKey},
"/delete/data/openai_auth_key": {"status": True, "variable":controller.delOpenAiAuthKey},
"/get/data/convert_message_to_romaji": {"status": True, "variable":controller.getConvertMessageToRomaji}, "/get/data/convert_message_to_romaji": {"status": True, "variable":controller.getConvertMessageToRomaji},
"/set/enable/convert_message_to_romaji": {"status": True, "variable":controller.setEnableConvertMessageToRomaji}, "/set/enable/convert_message_to_romaji": {"status": True, "variable":controller.setEnableConvertMessageToRomaji},
"/set/disable/convert_message_to_romaji": {"status": True, "variable":controller.setDisableConvertMessageToRomaji}, "/set/disable/convert_message_to_romaji": {"status": True, "variable":controller.setDisableConvertMessageToRomaji},

View File

@@ -198,14 +198,57 @@ class Model:
result = self.translator.authenticationDeepLAuthKey(auth_key) result = self.translator.authenticationDeepLAuthKey(auth_key)
return result return result
def authenticationTranslatorPlamoAuthKey(self, auth_key: str, model: str) -> bool: def authenticationTranslatorPlamoAuthKey(self, auth_key: str) -> bool:
result = self.translator.authenticationPlamoAuthKey(auth_key, model=model, root_path=config.PATH_LOCAL) result = self.translator.authenticationPlamoAuthKey(auth_key, root_path=config.PATH_LOCAL)
return result return result
def authenticationTranslatorGeminiAuthKey(self, auth_key: str, model: str) -> bool: def getTranslatorPlamoModelList(self) -> list[str]:
result = self.translator.authenticationGeminiAuthKey(auth_key, model=model, root_path=config.PATH_LOCAL) self.ensure_initialized()
return self.translator.getPlamoModelList()
def setTranslatorPlamoModel(self, model: str) -> bool:
self.ensure_initialized()
result = self.translator.setPlamoModel(model=model)
return result return result
def updateTranslatorPlamoClient(self) -> None:
self.ensure_initialized()
self.translator.updatePlamoClient()
def authenticationTranslatorGeminiAuthKey(self, auth_key: str) -> bool:
result = self.translator.authenticationGeminiAuthKey(auth_key, root_path=config.PATH_LOCAL)
return result
def getTranslatorGeminiModelList(self) -> list[str]:
self.ensure_initialized()
return self.translator.getGeminiModelList()
def setTranslatorGeminiModel(self, model: str) -> bool:
self.ensure_initialized()
result = self.translator.setGeminiModel(model=model)
return result
def updateTranslatorGeminiClient(self) -> None:
self.ensure_initialized()
self.translator.updateGeminiClient()
def authenticationTranslatorOpenAIAuthKey(self, auth_key: str, base_url: Optional[str] = None) -> bool:
result = self.translator.authenticationOpenAIAuthKey(auth_key, base_url=base_url, root_path=config.PATH_LOCAL)
return result
def getTranslatorOpenAIModelList(self) -> list[str]:
self.ensure_initialized()
return self.translator.getOpenAIModelList()
def setTranslatorOpenAiModel(self, model: str) -> bool:
self.ensure_initialized()
result = self.translator.setOpenAIModel(model=model)
return result
def updateTranslatorOpenAIClient(self) -> None:
self.ensure_initialized()
self.translator.updateOpenAIClient()
def startLogger(self): def startLogger(self):
self.ensure_initialized() self.ensure_initialized()
os_makedirs(config.PATH_LOGS, exist_ok=True) os_makedirs(config.PATH_LOGS, exist_ok=True)

View File

@@ -1,7 +1,10 @@
system_prompt: | system_prompt: |
Please translate the following text from {input_lang} to {output_lang}. You are a helpful translation assistant.
Only provide the translated text as the output. Supported languages:
{text} {supported_languages}
Translate the user provided text from {input_lang} to {output_lang}.
Return ONLY the translated text. Do not add quotes or extra commentary.
supported_languages: | supported_languages: |
Arabic Arabic

View File

@@ -0,0 +1,49 @@
system_prompt: |
You are a helpful translation assistant.
Supported languages:
{supported_languages}
Translate the user provided text from {input_lang} to {output_lang}.
Return ONLY the translated text. Do not add quotes or extra commentary.
supported_languages: |
Arabic
Bengali
Bulgarian
Catalan
Chinese Simplified
Chinese Traditional
Croatian
Czech
Danish
Dutch
English
Estonian
Finnish
French
German
Greek
Hebrew
Hindi
Hungarian
Indonesian
Italian
Japanese
Korean
Latvian
Lithuanian
Norwegian
Polish
Portuguese
Romanian
Russian
Serbian
Slovak
Slovenian
Spanish
Swahili
Swedish
Thai
Turkish
Ukrainian
Vietnamese

View File

@@ -1,148 +1,138 @@
import logging import logging
from google import genai
from langchain_google_genai import ChatGoogleGenerativeAI from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import HumanMessage
import yaml import yaml
from os import path as os_path from os import path as os_path
logger = logging.getLogger("langchain_google_genai") logger = logging.getLogger("langchain_google_genai")
logger.setLevel(logging.ERROR) logger.setLevel(logging.ERROR)
_MODELS = [ def _authentication_check(api_key: str) -> bool:
"gemini-2.5-pro", """Check if the provided API key is valid by attempting to list models.
"gemini-2.5-flash", """
"gemini-2.5-flash-lite", # default try:
"gemini-2.0-flash", client = genai.Client(api_key=api_key)
"gemini-2.0-flash-lite", client.models.list()
"gemini-1.5-pro", return True
"gemini-1.5-flash-8b" except Exception:
"gemini-1.5-flash", return False
def _get_available_text_models(api_key: str) -> list[str]:
"""Extract only Gemini models suitable for translation and chat applications
"""
client = genai.Client(api_key=api_key)
res = client.models.list()
allowed_models = []
# 除外対象のキーワード
exclude_keywords = [
"audio",
"image",
"veo",
"tts",
"robotics",
"computer-use"
] ]
for model in res:
model_id = model.name
if ("gemini" in model_id.lower() or "gemma" in model_id.lower()) and "generateContent" in model.supported_actions:
if any(x in model_id for x in exclude_keywords):
continue
allowed_models.append(model_id.replace("models/", ""))
allowed_models.sort()
return allowed_models
def _load_prompt_config(root_path: str = None) -> dict:
"""プロンプト設定をYAMLファイルから読み込む"""
prompt_filename = "translation_gemini.yml"
# PyInstallerでビルドされた場合のパス
if root_path and os_path.exists(os_path.join(root_path, "_internal", "prompt", prompt_filename)):
prompt_path = os_path.join(root_path, "_internal", "prompt", prompt_filename)
# src-pythonフォルダから直接実行している場合のパス
elif os_path.exists(os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)
# translationフォルダから直接実行している場合のパス
elif os_path.exists(os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)
else:
raise FileNotFoundError(f"Prompt file not found: {prompt_filename}")
with open(prompt_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
class GeminiClient: class GeminiClient:
def __init__(self, api_key: str = "", model: str = "gemini-2.5-flash-lite", root_path: str = None): def __init__(self, root_path: str = None):
self.api_key = api_key self.api_key = None
self.model = model self.model = None
# プロンプト設定をYAMLファイルから読み込む # プロンプト設定をYAMLファイルから読み込む
prompt_config = self._load_prompt_config(root_path) prompt_config = _load_prompt_config(root_path)
self.supported_languages = prompt_config["supported_languages"] self.supported_languages = prompt_config["supported_languages"]
self.prompt_template = prompt_config["system_prompt"] self.prompt_template = prompt_config["system_prompt"]
self.gemini_llm = None
def getModelList(self) -> list[str]:
return _get_available_text_models(self.api_key)
def getAuthKey(self) -> str:
return self.api_key
def setAuthKey(self, api_key: str) -> bool:
result = _authentication_check(api_key)
if result:
self.api_key = api_key
return result
def getModel(self) -> str:
return self.model
def setModel(self, model: str) -> bool:
if model in self.getModelList():
self.model = model
return True
else:
return False
def updateClient(self) -> None:
self.gemini_llm = ChatGoogleGenerativeAI( self.gemini_llm = ChatGoogleGenerativeAI(
model=self.model, model=self.model,
api_key=self.api_key, api_key=self.api_key,
) )
def _load_prompt_config(self, root_path: str = None) -> dict:
"""プロンプト設定をYAMLファイルから読み込む"""
prompt_filename = "translation_gemini.yml"
# PyInstallerでビルドされた場合のパス
if root_path and os_path.exists(os_path.join(root_path, "_internal", "prompt", prompt_filename)):
prompt_path = os_path.join(root_path, "_internal", "prompt", prompt_filename)
# src-pythonフォルダから直接実行している場合のパス
elif os_path.exists(os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)
# translationフォルダから直接実行している場合のパス
elif os_path.exists(os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)
else:
raise FileNotFoundError(f"Prompt file not found: {prompt_filename}")
with open(prompt_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
def getListModels(self) -> list[str]:
return _MODELS
def getAuthKey(self) -> str:
"""現在のAuthKeyを取得する"""
return self.api_key
def getModel(self) -> str:
"""現在のモデルを取得する"""
return self.model
def setAuthKey(self, api_key: str) -> bool:
"""AuthKeyを設定し、成功したかどうかを返す"""
try:
self.api_key = api_key
self.gemini_llm = ChatGoogleGenerativeAI(
model=self.model,
api_key=self.api_key,
)
return True
except Exception as e:
print(f"Error setting AuthKey: {e}")
return False
def setModel(self, model: str) -> bool:
"""モデルを設定し、成功したかどうかを返す"""
try:
if model in _MODELS:
self.model = model
self.gemini_llm = ChatGoogleGenerativeAI(
model=self.model,
api_key=self.api_key,
)
return True
else:
print(f"Model {model} is not supported.")
return False
except Exception as e:
print(f"Error setting model: {e}")
return False
def translate(self, text: str, input_lang: str, output_lang: str) -> str: def translate(self, text: str, input_lang: str, output_lang: str) -> str:
messages = self.prompt_template.format( system_prompt = self.prompt_template.format(
input_lang=input_lang, supported_languages=self.supported_languages,
output_lang=output_lang, input_lang=input_lang,
text=text output_lang=output_lang
) )
output = self.gemini_llm.invoke([HumanMessage(content=messages)]) messages = [
return output.content {"role": "system", "content": system_prompt},
{"role": "user", "content": text}
]
def checkAuthKey(self) -> bool: resp = self.gemini_llm.invoke(messages)
try: content = ""
self.setModel(self.model) if isinstance(resp.content, str):
self.translate("Hello World", input_lang="English", output_lang="Japanese") content = resp.content
return True elif isinstance(resp.content, list):
except Exception: for part in resp.content:
return False if isinstance(part, str):
content += part
elif isinstance(part, dict) and "content" in part and isinstance(part["content"], str):
content += part["content"]
return content.strip()
if __name__ == "__main__": if __name__ == "__main__":
AUTH_KEY = "AUTH_KEY" AUTH_KEY = "AUTH_KEY"
text = """ client = GeminiClient()
毎朝コーヒーを入れるのがささやかな楽しみになってる client.setAuthKey(AUTH_KEY)
""" models = client.getModelList()
input_lang = "Japanese" if models:
output_lang = "English" print("Available models:", models)
model = input("Select a model: ")
gemini_client = GeminiClient(api_key=AUTH_KEY, model="gemini-2.5-flash-lite") client.setModel(model)
client.updateClient()
print("model list:", gemini_client.getListModels()) print(client.translate("こんにちは世界", "Japanese", "English"))
print("AuthKey:", gemini_client.getAuthKey())
# print("Model:", gemini_client.getModel())
# print(f"set model: {gemini_client.setModel('gemini-2.5-flash')}")
# print(f"set AuthKey: {gemini_client.setAuthKey(AUTH_KEY)}")
# print(f"check AuthKey: {gemini_client.checkAuthKey()}")
# try:
# translated_text = gemini_client.translate(text, input_lang, output_lang)
# print(translated_text)
# except Exception:
# print("Invalid API key. Please check your credentials.")
# 外部ファイルから読み込んだサポート言語を使用
for lang in gemini_client.supported_languages.split("\n"):
if lang == "":
continue
print (f"Translating to {lang}:")
try:
translated_text = gemini_client.translate(text, input_lang, lang)
print(f"Translated text: {translated_text}")
except Exception as e:
print(f"Error translating to {lang} api limit")
print(f"Error reason: {e}")
break

View File

@@ -664,3 +664,49 @@ dict_gemini_languages = {
} }
translation_lang["Gemini_API"] = {"source":dict_gemini_languages, "target":dict_gemini_languages} translation_lang["Gemini_API"] = {"source":dict_gemini_languages, "target":dict_gemini_languages}
# OpenAI API (Chat Completions) - Gemini とほぼ同等の自然言語名を使用
dict_openai_languages = {
"Arabic": "Arabic",
"Bengali": "Bengali",
"Bulgarian": "Bulgarian",
"Catalan": "Catalan",
"Chinese Simplified": "Simplified Chinese",
"Chinese Traditional": "Traditional Chinese",
"Croatian": "Croatian",
"Czech": "Czech",
"Danish": "Danish",
"Dutch": "Dutch",
"English": "English",
"Estonian": "Estonian",
"Finnish": "Finnish",
"French": "French",
"German": "German",
"Greek": "Greek",
"Hebrew": "Hebrew",
"Hindi": "Hindi",
"Hungarian": "Hungarian",
"Indonesian": "Indonesian",
"Italian": "Italian",
"Japanese": "Japanese",
"Korean": "Korean",
"Latvian": "Latvian",
"Lithuanian": "Lithuanian",
"Norwegian": "Norwegian",
"Polish": "Polish",
"Portuguese": "Portuguese",
"Romanian": "Romanian",
"Russian": "Russian",
"Serbian": "Serbian",
"Slovak": "Slovak",
"Slovenian": "Slovenian",
"Spanish": "Spanish",
"Swahili": "Swahili",
"Swedish": "Swedish",
"Thai": "Thai",
"Turkish": "Turkish",
"Ukrainian": "Ukrainian",
"Vietnamese": "Vietnamese",
}
translation_lang["OpenAI_API"] = {"source": dict_openai_languages, "target": dict_openai_languages}

View File

@@ -0,0 +1,148 @@
from openai import OpenAI
from langchain_openai import ChatOpenAI
from pydantic import SecretStr
import yaml
from os import path as os_path
def _authentication_check(api_key: str, base_url: str | None = None) -> bool:
"""Check if the provided API key is valid by attempting to list models.
"""
try:
client = OpenAI(api_key=api_key, base_url=base_url)
client.models.list()
return True
except Exception:
return False
def _get_available_text_models(api_key: str, base_url: str | None = None) -> list[str]:
"""Extract only GPT models suitable for translation and chat applications (plus those with fine-tuning)
"""
client = OpenAI(api_key=api_key, base_url=base_url)
res = client.models.list()
allowed_models = []
for model in res.data:
model_id = model.id
root = getattr(model, "root", "")
# 除外対象のキーワード
exclude_keywords = [
"whisper", # 音声認識
"embedding", # 埋め込み
"image", # 画像生成
"tts", # 音声合成
"audio", # 音声系transcribe, diarize含む
"search", # 検索補助モデル
"transcribe", # 音声→文字起こし
"diarize", # 話者分離
"vision" # 画像入力系旧gpt-4-visionなど
]
# 除外キーワードが含まれているモデルをスキップ
if any(kw in model_id for kw in exclude_keywords):
continue
# GPTモデルまたはFine-tune GPTモデルのみ対象
if model_id.startswith("gpt-"):
allowed_models.append(model_id)
elif model_id.startswith("ft:") and root.startswith("gpt-"):
allowed_models.append(model_id)
allowed_models.sort()
return allowed_models
def _load_prompt_config(root_path: str = None) -> dict:
prompt_filename = "translation_openai.yml"
# PyInstaller 展開後
if root_path and os_path.exists(os_path.join(root_path, "_internal", "prompt", prompt_filename)):
prompt_path = os_path.join(root_path, "_internal", "prompt", prompt_filename)
# src-python 直下実行
elif os_path.exists(os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)
# translation フォルダ直下実行
elif os_path.exists(os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)
else:
raise FileNotFoundError(f"Prompt file not found: {prompt_filename}")
with open(prompt_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
class OpenAIClient:
"""OpenAI Translation simple wrapper.
prompt/translation_openai.yml から system_prompt / supported_languages を読み込む。
"""
def __init__(self, base_url: str | None = None, root_path: str = None):
self.api_key = None
self.model = None
self.base_url = base_url # None の場合は公式エンドポイント
prompt_config = _load_prompt_config(root_path)
self.supported_languages = prompt_config["supported_languages"]
self.prompt_template = prompt_config["system_prompt"]
self.openai_llm = None
def getModelList(self) -> list[str]:
return _get_available_text_models(self.api_key, self.base_url) if self.api_key else []
def getAuthKey(self) -> str:
return self.api_key
def setAuthKey(self, api_key: str) -> bool:
result = _authentication_check(api_key, self.base_url)
if result:
self.api_key = api_key
return result
def getModel(self) -> str:
return self.model
def setModel(self, model: str) -> bool:
if model in self.getModelList():
self.model = model
return True
else:
return False
def updateClient(self) -> None:
self.openai_llm = ChatOpenAI(
base_url=self.base_url,
model=self.model,
api_key=SecretStr(self.api_key),
streaming=False,
)
def translate(self, text: str, input_lang: str, output_lang: str) -> str:
system_prompt = self.prompt_template.format(
supported_languages=self.supported_languages,
input_lang=input_lang,
output_lang=output_lang,
)
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": text},
]
resp = self.openai_llm.invoke(messages)
content = ""
if isinstance(resp.content, str):
content = resp.content
elif isinstance(resp.content, list):
for part in resp.content:
if isinstance(part, str):
content += part
elif isinstance(part, dict) and "content" in part and isinstance(part["content"], str):
content += part["content"]
return content.strip()
if __name__ == "__main__":
AUTH_KEY = "OPENAI_API_KEY"
client = OpenAIClient()
client.setAuthKey(AUTH_KEY)
models = client.getModelList()
if models:
print("Available models:", models)
model = input("Select a model: ")
client.setModel(model)
client.updateClient()
print(client.translate("こんにちは世界", "Japanese", "English"))

View File

@@ -1,147 +1,126 @@
from openai import OpenAI
from langchain_openai import ChatOpenAI from langchain_openai import ChatOpenAI
from pydantic import SecretStr from pydantic import SecretStr
import yaml import yaml
from os import path as os_path from os import path as os_path
_MODELS = [ BASE_URL = "https://api.platform.preferredai.jp/v1"
"plamo-2.0-prime"
] def _authentication_check(api_key: str) -> bool:
"""Check if the provided API key is valid by attempting to list models.
"""
try:
client = OpenAI(api_key=api_key, base_url=BASE_URL)
client.models.list()
return True
except Exception:
return False
def _get_available_text_models(api_key: str) -> list[str]:
"""Extract all available models from the PLAMO API
"""
client = OpenAI(api_key=api_key, base_url=BASE_URL)
res = client.models.list()
allowed_models = []
for model in res.data:
allowed_models.append(model.id)
allowed_models.sort()
return allowed_models
def _load_prompt_config(root_path: str = None) -> dict:
"""プロンプト設定をYAMLファイルから読み込む"""
prompt_filename = "translation_plamo.yml"
# PyInstallerでビルドされた場合のパス
if root_path and os_path.exists(os_path.join(root_path, "_internal", "prompt", prompt_filename)):
prompt_path = os_path.join(root_path, "_internal", "prompt", prompt_filename)
# src-pythonフォルダから直接実行している場合のパス
elif os_path.exists(os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)
# translationフォルダから直接実行している場合のパス
elif os_path.exists(os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)
else:
raise FileNotFoundError(f"Prompt file not found: {prompt_filename}")
with open(prompt_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
class PlamoClient: class PlamoClient:
def __init__(self, api_key: str = "", model: str = "plamo-2.0-prime", root_path: str = None): def __init__(self, root_path: str = None):
self.api_key = api_key self.api_key = None
self.base_url = "https://api.platform.preferredai.jp/v1" self.base_url = BASE_URL
self.model = model self.model = None
# プロンプト設定をYAMLファイルから読み込む prompt_config = _load_prompt_config(root_path)
prompt_config = self._load_prompt_config(root_path)
self.supported_languages = prompt_config["supported_languages"] self.supported_languages = prompt_config["supported_languages"]
self.prompt_template = prompt_config["system_prompt"] self.prompt_template = prompt_config["system_prompt"]
self.plamo_llm = None
def getModelList(self) -> list[str]:
return _get_available_text_models(self.api_key) if self.api_key else []
def getAuthKey(self) -> str:
return self.api_key
def setAuthKey(self, api_key: str) -> bool:
result = _authentication_check(api_key)
if result:
self.api_key = api_key
return result
def getModel(self) -> str:
return self.model
def setModel(self, model: str) -> bool:
if model in self.getModelList():
self.model = model
return True
else:
return False
def updateClient(self) -> None:
self.plamo_llm = ChatOpenAI( self.plamo_llm = ChatOpenAI(
base_url=self.base_url, base_url=self.base_url,
model=self.model, model=self.model,
streaming=True, streaming=False,
api_key=SecretStr(self.api_key), api_key=SecretStr(self.api_key),
) )
def _load_prompt_config(self, root_path: str = None) -> dict:
"""プロンプト設定をYAMLファイルから読み込む"""
prompt_filename = "translation_plamo.yml"
# PyInstallerでビルドされた場合のパス
if root_path and os_path.exists(os_path.join(root_path, "_internal", "prompt", prompt_filename)):
prompt_path = os_path.join(root_path, "_internal", "prompt", prompt_filename)
# src-pythonフォルダから直接実行している場合のパス
elif os_path.exists(os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "models", "translation", "prompt", prompt_filename)
# translationフォルダから直接実行している場合のパス
elif os_path.exists(os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)):
prompt_path = os_path.join(os_path.dirname(__file__), "prompt", prompt_filename)
else:
raise FileNotFoundError(f"Prompt file not found: {prompt_filename}")
with open(prompt_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
def getListModels(self) -> list[str]:
return _MODELS
def getAuthKey(self) -> str:
"""現在のAuthKeyを取得する"""
return self.api_key
def getModel(self) -> str:
"""現在のモデルを取得する"""
return self.model
def setAuthKey(self, api_key: str) -> bool:
"""AuthKeyを設定し、成功したかどうかを返す"""
try:
self.api_key = api_key
self.plamo_llm = ChatOpenAI(
base_url=self.base_url,
model=self.model,
streaming=True,
api_key=SecretStr(self.api_key),
)
return True
except Exception as e:
return False
def setModel(self, model: str) -> bool:
"""モデルを設定し、成功したかどうかを返す"""
if model not in _MODELS:
return False
try:
self.model = model
self.plamo_llm = ChatOpenAI(
base_url=self.base_url,
model=self.model,
streaming=True,
api_key=SecretStr(self.api_key),
)
return True
except Exception as e:
print(f"Error setting model: {e}")
return False
def translate(self, text: str, input_lang: str, output_lang: str) -> str: def translate(self, text: str, input_lang: str, output_lang: str) -> str:
system_prompt = self.prompt_template.format(
supported_languages=self.supported_languages,
input_lang=input_lang,
output_lang=output_lang
)
messages = [ messages = [
{ {"role": "system", "content": system_prompt},
"role": "system",
"content": self.prompt_template.format(
supported_languages=self.supported_languages,
input_lang=input_lang,
output_lang=output_lang
),
},
{"role": "user", "content": text}, {"role": "user", "content": text},
] ]
output = "" resp = self.plamo_llm.invoke(messages)
for chunk in self.plamo_llm.stream(messages): content = ""
if isinstance(chunk.content, str): if isinstance(resp.content, str):
output += chunk.content content = resp.content
elif isinstance(chunk.content, list): elif isinstance(resp.content, list):
for item in chunk.content: for part in resp.content:
if isinstance(item, str): if isinstance(part, str):
output += item content += part
elif isinstance(item, dict): elif isinstance(part, dict) and "content" in part and isinstance(part["content"], str):
if "content" in item and isinstance(item["content"], str): content += part["content"]
output += item["content"] return content.strip()
return output[:-1]
def checkAuthKey(self) -> bool:
try:
self.setModel(self.model)
self.translate("Hello World", input_lang="English", output_lang="Japanese")
return True
except Exception as e:
print(f"Error checking AuthKey: {e}")
return False
if __name__ == "__main__": if __name__ == "__main__":
AUTH_KEY = "AUTH_KEY" AUTH_KEY = "PLAMO_API_KEY"
text = """ client = PlamoClient()
毎朝コーヒーを入れるのがささやかな楽しみになってる client.setAuthKey(AUTH_KEY)
""" models = client.getModelList()
input_lang = "Japanese" if models:
output_lang = "English" print("Available models:", models)
model = input("Select a model: ")
plamo_client = PlamoClient(api_key=AUTH_KEY) client.setModel(model)
client.updateClient()
print("model list:", plamo_client.getListModels()) print(client.translate("こんにちは世界", "Japanese", "English"))
print("AuthKey:", plamo_client.getAuthKey())
print("Model:", plamo_client.getModel())
print(f"set model: {plamo_client.setModel('plamo-2.0-prime')}")
print(f"set AuthKey: {plamo_client.setAuthKey(AUTH_KEY)}")
print(f"check AuthKey: {plamo_client.checkAuthKey()}")
try:
translated_text = plamo_client.translate(text, input_lang, output_lang)
print(translated_text)
except Exception:
print("Invalid API key. Please check your credentials.")

View File

@@ -12,6 +12,7 @@ try:
from .translation_utils import ctranslate2_weights from .translation_utils import ctranslate2_weights
from .translation_plamo import PlamoClient from .translation_plamo import PlamoClient
from .translation_gemini import GeminiClient from .translation_gemini import GeminiClient
from .translation_openai import OpenAIClient
except Exception: except Exception:
import sys import sys
print(os_path.dirname(os_path.dirname(os_path.dirname(os_path.abspath(__file__))))) print(os_path.dirname(os_path.dirname(os_path.dirname(os_path.abspath(__file__)))))
@@ -20,6 +21,7 @@ except Exception:
from translation_utils import ctranslate2_weights from translation_utils import ctranslate2_weights
from translation_plamo import PlamoClient from translation_plamo import PlamoClient
from translation_gemini import GeminiClient from translation_gemini import GeminiClient
from translation_openai import OpenAIClient
import ctranslate2 import ctranslate2
import transformers import transformers
@@ -44,6 +46,7 @@ class Translator:
self.deepl_client: Optional[DeepLClient] = None self.deepl_client: Optional[DeepLClient] = None
self.plamo_client: Optional[PlamoClient] = None self.plamo_client: Optional[PlamoClient] = None
self.gemini_client: Optional[GeminiClient] = None self.gemini_client: Optional[GeminiClient] = None
self.openai_client: Optional[OpenAIClient] = None
self.ctranslate2_translator: Any = None self.ctranslate2_translator: Any = None
self.ctranslate2_tokenizer: Any = None self.ctranslate2_tokenizer: Any = None
self.is_loaded_ctranslate2_model: bool = False self.is_loaded_ctranslate2_model: bool = False
@@ -66,35 +69,107 @@ class Translator:
result = False result = False
return result return result
def authenticationPlamoAuthKey(self, auth_key: str, model: str, root_path: str = None) -> bool: def authenticationPlamoAuthKey(self, auth_key: str, root_path: str = None) -> bool:
"""Authenticate Plamo API with the provided key. """Authenticate Plamo API with the provided key.
Returns True on success, False on failure. Returns True on success, False on failure.
""" """
result = True self.plamo_client = PlamoClient(root_path=root_path)
try: if self.plamo_client.setAuthKey(auth_key):
self.plamo_client = PlamoClient(auth_key, model=model, root_path=root_path) return True
self.plamo_client.checkAuthKey() else:
except Exception:
errorLogging()
self.plamo_client = None self.plamo_client = None
result = False return False
return result
def authenticationGeminiAuthKey(self, auth_key: str, model: str, root_path: str = None) -> bool: def getPlamoModelList(self) -> list[str]:
"""Get available Plamo models.
Returns a list of model names, or an empty list on failure.
"""
if self.plamo_client is None:
return []
return self.plamo_client.getModelList()
def setPlamoModel(self, model: str) -> bool:
"""Change the Plamo model used for translation.
Returns True on success, False on failure.
"""
if self.plamo_client is None:
return False
return self.plamo_client.setModel(model)
def updatePlamoClient(self) -> None:
"""Update the Plamo client (fetch available models)."""
self.plamo_client.updateClient()
def authenticationGeminiAuthKey(self, auth_key: str, root_path: str = None) -> bool:
"""Authenticate Gemini API with the provided key. """Authenticate Gemini API with the provided key.
Returns True on success, False on failure. Returns True on success, False on failure.
""" """
result = True self.gemini_client = GeminiClient(root_path=root_path)
try: if self.gemini_client.setAuthKey(auth_key):
self.gemini_client = GeminiClient(auth_key, model=model, root_path=root_path) return True
self.gemini_client.checkAuthKey() else:
except Exception: return False
errorLogging()
self.gemini_client = None def getGeminiModelList(self) -> list[str]:
result = False """Get available Gemini models.
return result
Returns a list of model names, or an empty list on failure.
"""
if self.gemini_client is None:
return []
return self.gemini_client.getModelList()
def setGeminiModel(self, model: str) -> bool:
"""Change the Gemini model used for translation.
Returns True on success, False on failure.
"""
if self.gemini_client is None:
return False
return self.gemini_client.setModel(model)
def updateGeminiClient(self) -> None:
"""Update the Gemini client (fetch available models)."""
self.gemini_client.updateClient()
def authenticationOpenAIAuthKey(self, auth_key: str, base_url: str | None = None, root_path: str = None) -> bool:
"""Authenticate OpenAI (Chat Completions) API with the provided key.
base_url を指定することで互換エンドポイント (例: Azure OpenAI 互換, Proxy) にも対応可能。
Returns True on success, False on failure.
"""
self.openai_client = OpenAIClient(base_url=base_url, root_path=root_path)
if self.openai_client.setAuthKey(auth_key):
return True
else:
self.openai_client = None
return False
def getOpenAIModelList(self) -> list[str]:
"""Get available OpenAI models.
Returns a list of model names, or an empty list on failure.
"""
if self.openai_client is None:
return []
return self.openai_client.getModelList()
def setOpenAIModel(self, model: str) -> bool:
"""Change the OpenAI model used for translation.
Returns True on success, False on failure.
"""
if self.openai_client is None:
return False
return self.openai_client.setModel(model)
def updateOpenAIClient(self) -> None:
"""Update the OpenAI client (fetch available models)."""
self.openai_client.updateClient()
def changeCTranslate2Model(self, path: str, model_type: str, device: str = "cpu", device_index: int = 0, compute_type: str = "auto") -> None: def changeCTranslate2Model(self, path: str, model_type: str, device: str = "cpu", device_index: int = 0, compute_type: str = "auto") -> None:
"""Load a CTranslate2 model from weights. """Load a CTranslate2 model from weights.
@@ -236,6 +311,15 @@ class Translator:
input_lang=source_language, input_lang=source_language,
output_lang=target_language, output_lang=target_language,
) )
case "OpenAI_API":
if self.openai_client is None:
result = False
else:
result = self.openai_client.translate(
message,
input_lang=source_language,
output_lang=target_language,
)
case "Google": case "Google":
if self.is_enable_translators is True and other_web_Translator is not None: if self.is_enable_translators is True and other_web_Translator is not None:
result = other_web_Translator( result = other_web_Translator(