Files

194 lines
11 KiB
Python

import os
import folder_paths
import time
import torch
from ..UL_common.common import get_dtype_by_name
from comfy.model_management import get_torch_device, text_encoder_offload_device, soft_empty_cache
from comfy.utils import ProgressBar
current_directory = os.path.dirname(os.path.abspath(__file__))
class UL_TranslatorLoader:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"model_name": (["utrobinmv/t5_translate_en_ru_zh_small_1024", "iic/nlp_csanmt_translation_zh2en", "iic/nlp_csanmt_translation_en2zh", "iic/nlp_csanmt_translation_en2zh_base", "botisan-ai/mt5-translate-zh-yue", "facebook/nllb-200-distilled-600M", "facebook/nllb-200-distilled-1.3B", "facebook/nllb-200-3.3B"], {"default": "utrobinmv/t5_translate_en_ru_zh_small_1024", "tooltip": ""}),
"weight_dtype": (["auto", "fp16", "bf16", "fp32", "fp8_e4m3fn", "fp8_e4m3fnuz", "fp8_e5m2", "fp8_e5m2fnuz"],{"default":"auto", "tooltip": "For t5、nllb."}),
"Auto_Download_Path": ("BOOLEAN", {"default": True, "label_on": "models_local本地", "label_off": ".cache缓存", "tooltip": "Download to `ComfyUI\models\prompt_generator` or huggingface cache dir.\n下载模型到`ComfyUI\models\prompt_generator`或者缓存到huggingface缓存路径。"}),
}
}
RETURN_TYPES = ("TRANSLATE_MODEL", "STRING", )
RETURN_NAMES = ("model", "model_dir", )
CATEGORY = "UL Group/Data Process"
FUNCTION = "main"
TITLE = "Translator Loader"
DESCRIPTION = ""
def main(self, model_name, weight_dtype, Auto_Download_Path):
dtype = get_dtype_by_name(weight_dtype)
prompt_generator_dir = os.path.join(folder_paths.models_dir, "prompt_generator")
if 'nlp_csanmt_translation' in model_name.lower():
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
nlp_device = 'cuda' if 'cuda' in get_torch_device().type else "cpu"
model_dir = os.path.join(prompt_generator_dir, "modelscope--damo--nlp_csanmt_translation_zh2en") if "zh2en" in model_name.lower() else os.path.join(prompt_generator_dir, "modelscope--damo--nlp_csanmt_translation_en2zh_base") if "en2zh_base" in model_name.lower() else os.path.join(prompt_generator_dir, "modelscope--damo--nlp_csanmt_translation_en2zh")
if not os.path.exists(os.path.join(model_dir, "tf_ckpts", "ckpt-0.data-00000-of-00001")):
if Auto_Download_Path:
from modelscope.hub.snapshot_download import snapshot_download
snapshot_download(
model_id=model_name,
local_dir=model_dir,
)
else:
model_dir = model_name
model = pipeline(task=Tasks.translation, model=model_dir, device=nlp_device)
tokenizer = "None"
model_type = "nlp"
elif model_name == "botisan-ai/mt5-translate-zh-yue":
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
model_dir = os.path.join(prompt_generator_dir, "models--botisan-ai--mt5-translate-zh-yue")
if not os.path.exists(os.path.join(model_dir, "model.safetensors")):
if Auto_Download_Path:
from huggingface_hub import snapshot_download
snapshot_download(
repo_id=model_name,
local_dir=model_dir,
ignore_patterns=["*.bin"]
)
else:
model_dir = model_name
tokenizer = AutoTokenizer.from_pretrained(model_dir)
model = AutoModelForSeq2SeqLM.from_pretrained(model_dir)
model_type = "mt5"
elif "nllb-200" in model_name.lower():
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
model_dir = os.path.join(prompt_generator_dir, f'models--{model_name.replace("/", "--")}')
if not os.path.exists(os.path.join(model_dir, "pytorch_model.bin")):
if Auto_Download_Path:
from huggingface_hub import snapshot_download
snapshot_download(
repo_id=model_name,
local_dir=model_dir,
)
else:
model_dir = model_name
tokenizer = AutoTokenizer.from_pretrained(model_dir)
model = AutoModelForSeq2SeqLM.from_pretrained(model_dir).to(dtype)
model_type = "nllb"
elif "t5_translate_en_ru_zh" in model_name.lower():
from transformers import T5ForConditionalGeneration, T5Tokenizer
model_dir = os.path.join(prompt_generator_dir, f'models--{model_name.replace("/", "--")}')
if not os.path.exists(os.path.join(model_dir, "model.safetensors")):
if Auto_Download_Path:
from huggingface_hub import snapshot_download
snapshot_download(
repo_id=model_name,
local_dir=model_dir,
)
else:
model_dir = model_name
tokenizer = T5Tokenizer.from_pretrained(model_dir)
model = T5ForConditionalGeneration.from_pretrained(model_dir).to(dtype)
model_type = "t5"
model = {
"model": model,
"tokenizer": tokenizer,
"model_type": model_type,
"dtype": dtype,
}
return (model, model_dir, )
class UL_Translator:
@classmethod
def INPUT_TYPES(cls):
from .Translate_Scripts.translate_backbone import language_list
return {
"required": {
"model": ("TRANSLATE_MODEL", ),
"string": ("STRING", {'default': '', "multiline": True, "dynamicPrompts": True}),
"src_language": (language_list, {"default": "", "tooltip": "For nllb."}),
"tgt_language": (language_list, {"default": "", "tooltip": "For nllb、t5."}),
"max_new_tokens": ("INT", {"default": 512, "min": 0, "max": 0xffffffffffffffff, "tooltip": "For mt5、nllb."}),
"use_fast": ("BOOLEAN", {"default": False, "label_on": "yes", "label_off": "no", "tooltip": "For nllb."}),
"keep_model_loaded": ("BOOLEAN", {"default": True, "label_on": "yes", "label_off": "no", "tooltip": "Warning: do not delete model unless this node no longer needed, it will try release device_memory and ram. if checked and want to continue node generation, use ComfyUI-Manager `Free model and node cache` to reset node state or change parameter in Loader node to activate.\n注意:仅在这个节点不再需要时删除模型,将尽量尝试释放系统内存和设备专用内存。如果删除后想继续使用此节点,使用ComfyUI-Manager插件的`Free model and node cache`重置节点状态或者更换模型加载节点的参数来激活。"}),
"keep_model_device": ("BOOLEAN", {"default": True, "label_on": "comfy", "label_off": "device", "tooltip": "Keep model in comfy_auto_unet_offload_device (HIGH_VRAM: device, Others: cpu) or device_memory after generation.\n生图完成后,模型转移到comfy自动选择设备(HIGH_VRAM: device, 其他: cpu)或者保留在设备专用内存上。"}),
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("string",)
CATEGORY = "UL Group/Data Process"
FUNCTION = "main"
TITLE = "Translator"
DESCRIPTION = ""
def main(self, model, string, src_language, tgt_language, max_new_tokens, keep_model_loaded, keep_model_device, use_fast):
from .Translate_Scripts.translate_backbone import nlp_tranlate, mt5_translate, nllb_translate, t5_language_map, t5_translate
sttime = time.time()
input_text = [string]
output_text = ""
if "\n" in string:
input_text = []
for txt in string.split("\n"):
input_text.append(txt)
pbar = ProgressBar(len(input_text))
for input in input_text:
if model['model_type'] == "nlp":
result = nlp_tranlate(model['model'], input)
output_text+=f'{result}\n'
pbar.update(1)
elif model['model_type'] == "mt5":
result = mt5_translate(model['model'], model['tokenizer'], input, max_new_tokens)
output_text+=f'{result}\n'
pbar.update(1)
elif model['model_type'] == "nllb":
if src_language != tgt_language:
result = nllb_translate(model['model'], model['tokenizer'], input, src_language, tgt_language, use_fast, max_new_tokens)
output_text+=f'{result}\n'
pbar.update(1)
else:
output_text = string
elif model['model_type'] == "t5":
if tgt_language in t5_language_map.keys():
result = t5_translate(model['model'], model['tokenizer'], input, t5_language_map[tgt_language])
output_text+=f'{result}\n'
pbar.update(1)
else:
output_text = string
endtime = time.time()
print("\n\033[93m翻译耗时:", endtime - sttime, "\033[0m")
if keep_model_loaded and keep_model_device and torch.cuda.is_available():
if model['model_type'] != "nlp":
model['model'].to(text_encoder_offload_device())
soft_empty_cache(True)
elif not keep_model_loaded:
del model['model'], model['tokenizer']
soft_empty_cache(True)
return (output_text, )
# Node class and display name mappings
NODE_CLASS_MAPPINGS = {
"UL_TranslatorLoader": UL_TranslatorLoader,
"UL_Translator": UL_Translator,
}
target_language_list = ["source", "zh", "yue", "en", "ru", "ja", "ko", "es", "fr", "it", "uk", "hi", "ar", "af", "am", "as", "az", "ba", "be", "bg", "bn", "bo", "br", "bs", "ca", "cs", "cy", "da", "de", "el", "et", "eu", "fa", "fi", "fo", "gl", "gu", "ha", "haw", "he", "hr", "ht", "hu", "hy", "id", "is", "jw", "ka", "kk", "km", "kn", "la", "lb", "ln", "lo", "lt", "lv", "mg", "mi", "mk", "ml", "mn", "mr", "ms", "mt", "my", "ne", "nl", "nn", "no", "oc", "pa", "pl", "ps", "pt", "ro", "sa", "sd", "si", "sk", "sl", "sn", "so", "sq", "sr", "su", "sv", "sw", "ta", "te", "tg", "th", "tk", "tl", "tr", "tt", "ur", "uz", "vi", "yi", "yo"]