[Add] translation_gemini: Integrate Gemini translation model and authentication; [Update] controller: Implement methods for managing Gemini models and auth keys; [Update] mainloop: Add routes for Gemini model and auth key management; [Update] translation: Enhance Translator class for Gemini API support; [Update] translation_languages: Add Gemini language mappings

This commit is contained in:
misyaguziya
2025-09-15 17:42:09 +09:00
parent e3555d204e
commit 224eaf3cef
7 changed files with 234 additions and 32 deletions

View File

@@ -10,6 +10,7 @@ from device_manager import device_manager
from models.translation.translation_languages import translation_lang
from models.translation.translation_utils import ctranslate2_weights
from models.translation.translation_plamo import _MODELS as plamo_models
from models.translation.translation_gemini import _MODELS as gemini_models
from models.transcription.transcription_languages import transcription_lang
from models.transcription.transcription_whisper import _MODELS as whisper_models
from utils import errorLogging, validateDictStructure
@@ -124,6 +125,10 @@ class Config:
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
def SELECTABLE_TRANSCRIPTION_ENGINE_LIST(self):
return self._SELECTABLE_TRANSCRIPTION_ENGINE_LIST
@@ -843,6 +848,18 @@ class Config:
self._PLAMO_MODEL = value
self.saveConfig(inspect.currentframe().f_code.co_name, value)
@property
@json_serializable('GEMINI_MODEL')
def GEMINI_MODEL(self):
return self._GEMINI_MODEL
@GEMINI_MODEL.setter
def GEMINI_MODEL(self, value):
if isinstance(value, str):
if value in self.SELECTABLE_GEMINI_MODEL_LIST:
self._GEMINI_MODEL = value
self.saveConfig(inspect.currentframe().f_code.co_name, value)
@property
@json_serializable('AUTO_CLEAR_MESSAGE_BOX')
def AUTO_CLEAR_MESSAGE_BOX(self):
@@ -1061,6 +1078,7 @@ class Config:
self._SELECTABLE_WHISPER_WEIGHT_TYPE_LIST = whisper_models.keys()
self._SELECTABLE_TRANSLATION_ENGINE_LIST = translation_lang.keys()
self._SELECTABLE_PLAMO_MODEL_LIST = plamo_models
self._SELECTABLE_GEMINI_MODEL_LIST = gemini_models
self._SELECTABLE_TRANSCRIPTION_ENGINE_LIST = list(transcription_lang[list(transcription_lang.keys())[0]].values())[0].keys()
self._SELECTABLE_UI_LANGUAGE_LIST = ["en", "ja", "ko", "zh-Hant", "zh-Hans"]
self._COMPUTE_MODE = "cuda" if torch.cuda.is_available() else "cpu"
@@ -1203,6 +1221,7 @@ class Config:
self._AUTH_KEYS = {
"DeepL_API": None,
"Plamo_API": None,
"Gemini_API": None,
}
self._USE_EXCLUDE_WORDS = True
self._SELECTED_TRANSLATION_COMPUTE_DEVICE = copy.deepcopy(self.SELECTABLE_COMPUTE_DEVICE_LIST[0])
@@ -1210,6 +1229,7 @@ class Config:
self._CTRANSLATE2_WEIGHT_TYPE = "m2m100_418M-ct2-int8"
self._WHISPER_WEIGHT_TYPE = "base"
self._PLAMO_MODEL = "plamo-2.0-prime"
self._GEMINI_MODEL = "gemini-2.5-flash-lite"
self._AUTO_CLEAR_MESSAGE_BOX = True
self._SEND_ONLY_TRANSLATED_MESSAGES = False
self._OVERLAY_SMALL_LOG = False

View File

@@ -1515,6 +1515,90 @@ class Controller:
self.updateTranslationEngineAndEngineList()
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 setGeminiModel(self, data, *args, **kwargs) -> dict:
printLog("Set Gemini Model", data)
try:
data = str(data)
result = model.authenticationTranslatorGeminiAuthKey(auth_key=config.AUTH_KEYS["Gemini_API"], model_name=data)
if result is True:
config.GEMINI_MODEL = data
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
def getGeminiAuthKey(self, *args, **kwargs) -> dict:
return {"status":200, "result":config.AUTH_KEYS["Gemini_API"]}
def setGeminiAuthKey(self, data, *args, **kwargs) -> dict:
printLog("Set Gemini Auth Key", data)
translator_name = "Gemini_API"
try:
data = str(data)
if len(data) >= 20:
result = model.authenticationTranslatorGeminiAuthKey(auth_key=data, model_name=config.GEMINI_MODEL)
if result is True:
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":"Authentication failure of gemini auth key",
"data": config.AUTH_KEYS[translator_name]
}
}
else:
response = {
"status":400,
"result":{
"message":"Gemini 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 delGeminiAuthKey(self, *args, **kwargs) -> dict:
translator_name = "Gemini_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]}
@staticmethod
def getCtranslate2WeightType(*args, **kwargs) -> dict:
return {"status":200, "result":config.CTRANSLATE2_WEIGHT_TYPE}

View File

@@ -174,6 +174,12 @@ mapping = {
"/set/data/plamo_auth_key": {"status": False, "variable":controller.setPlamoAuthKey},
"/delete/data/plamo_auth_key": {"status": False, "variable":controller.delPlamoAuthKey},
"/get/data/gemini_model_list": {"status": True, "variable":controller.getGeminiModelList},
"/set/data/gemini_model": {"status": True, "variable":controller.setGeminiModel},
"/get/data/gemini_auth_key": {"status": True, "variable":controller.getGeminiAuthKey},
"/set/data/gemini_auth_key": {"status": True, "variable":controller.setGeminiAuthKey},
"/delete/data/gemini_auth_key": {"status": True, "variable":controller.delGeminiAuthKey},
"/get/data/convert_message_to_romaji": {"status": True, "variable":controller.getConvertMessageToRomaji},
"/set/enable/convert_message_to_romaji": {"status": True, "variable":controller.setEnableConvertMessageToRomaji},
"/set/disable/convert_message_to_romaji": {"status": True, "variable":controller.setDisableConvertMessageToRomaji},

View File

@@ -144,6 +144,10 @@ class Model:
result = self.translator.authenticationPlamoAuthKey(auth_key, model=model)
return result
def authenticationTranslatorGeminiAuthKey(self, auth_key: str, model: str) -> bool:
result = self.translator.authenticationGeminiAuthKey(auth_key, model=model)
return result
def startLogger(self):
os_makedirs(config.PATH_LOGS, exist_ok=True)
file_name = os_path.join(config.PATH_LOGS, f"{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.log")

View File

@@ -1,10 +1,14 @@
import logging
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import HumanMessage
logger = logging.getLogger("langchain_google_genai")
logger.setLevel(logging.ERROR)
_MODELS = [
"gemini-2.5-pro",
"gemini-2.5-flash",
"gemini-2.5-flash-lite",
"gemini-2.5-flash-lite", # default
"gemini-2.0-flash",
"gemini-2.0-flash-lite",
"gemini-1.5-pro",
@@ -13,7 +17,7 @@ _MODELS = [
]
class GeminiClient:
def __init__(self, api_key: str = "", model: str = "gemini-2.5-flash"):
def __init__(self, api_key: str = "", model: str = "gemini-2.5-flash-lite"):
self.api_key = api_key
self.model = model
self.prompt_template = """
@@ -93,7 +97,7 @@ if __name__ == "__main__":
input_lang = "Japanese"
output_lang = "English"
gemini_client = GeminiClient(api_key=AUTH_KEY, model="gemini-1.5-flash")
gemini_client = GeminiClient(api_key=AUTH_KEY, model="gemini-2.5-flash-lite")
print("model list:", gemini_client.getListModels())
print("AuthKey:", gemini_client.getAuthKey())
@@ -110,41 +114,55 @@ if __name__ == "__main__":
supported_languages = """
English
Japanese
Korean
French
German
Spanish
Portuguese
Russian
Italian
Dutch
Polish
Turkish
Arabic
Hindi
Thai
Vietnamese
Indonesian
Malay
Filipino
Swedish
Finnish
Danish
Norwegian
Romanian
Czech
Hungarian
Greek
Hebrew
Bengali
Bulgarian
Simplified Chinese
Traditional Chinese
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
"""
for lang in 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

@@ -642,3 +642,50 @@ translation_lang["Plamo_API"] = {
"source":dict_plamo_languages,
"target":dict_plamo_languages,
}
dict_gemini_languages = {
"Arabic": "Arabic",
"Bengali": "Bengali",
"Bulgarian": "Bulgarian",
"Simplified Chinese": "Simplified Chinese",
"Traditional Chinese": "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["Gemini_API"] = {
"source":dict_gemini_languages,
"target":dict_gemini_languages,
}

View File

@@ -10,6 +10,7 @@ try:
from .translation_languages import translation_lang
from .translation_utils import ctranslate2_weights
from .translation_plamo import PlamoClient
from .translation_gemini import GeminiClient
except Exception:
import sys
print(os_path.dirname(os_path.dirname(os_path.dirname(os_path.abspath(__file__)))))
@@ -17,6 +18,7 @@ except Exception:
from translation_languages import translation_lang
from translation_utils import ctranslate2_weights
from translation_plamo import PlamoClient
from translation_gemini import GeminiClient
import ctranslate2
import transformers
@@ -30,6 +32,7 @@ class Translator():
def __init__(self):
self.deepl_client = None
self.plamo_client = None
self.gemini_client = None
self.ctranslate2_translator = None
self.ctranslate2_tokenizer = None
self.is_loaded_ctranslate2_model = False
@@ -57,6 +60,17 @@ class Translator():
result = False
return result
def authenticationGeminiAuthKey(self, auth_key: str, model: str) -> bool:
result = True
try:
self.gemini_client = GeminiClient(auth_key, model=model)
self.gemini_client.checkAuthKey()
except Exception:
errorLogging()
self.gemini_client = None
result = False
return result
def changeCTranslate2Model(self, path, model_type, device="cpu", device_index=0):
self.is_loaded_ctranslate2_model = False
directory_name = ctranslate2_weights[model_type]["directory_name"]
@@ -158,6 +172,15 @@ class Translator():
input_lang=source_language,
output_lang=target_language,
)
case "Gemini_API":
if self.gemini_client is None:
result = False
else:
result = self.gemini_client.translate(
message,
input_lang=source_language,
output_lang=target_language,
)
case "Google":
if self.is_enable_translators is True:
result = other_web_Translator(