Spaces:
Sleeping
Sleeping
v1.1.0
Browse files- app.py +141 -89
- config.json +42 -29
- requirements.txt +2 -1
- themes.py +3 -4
app.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import gradio as gr
|
|
|
2 |
from os import path as osp
|
3 |
import json
|
4 |
from utils import *
|
@@ -9,6 +10,12 @@ from themes import *
|
|
9 |
# idx指代顺序排列的序号,0,1,2,...
|
10 |
config_path = osp.join(osp.dirname(osp.abspath(__file__)),"./config.json")
|
11 |
args = load_config(config_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
if_save_id_immediately = True if int(args["if_save_id_immediately"]) else False
|
13 |
moyu_mode = True if int(args["moyu_mode"]) else False
|
14 |
path = args["file_path"]
|
@@ -16,7 +23,7 @@ abs_path = smart_path(path)
|
|
16 |
replace_dict_path = smart_path(args["replace_dict_path"])
|
17 |
name_dict_path = smart_path(args["name_dict_path"])
|
18 |
altered_text_finals= set()
|
19 |
-
|
20 |
|
21 |
if osp.exists(abs_path):
|
22 |
with open(abs_path, "r", encoding ="utf8") as json_file:
|
@@ -51,10 +58,25 @@ if osp.exists(name_dict_path):
|
|
51 |
name_dic[item[0]]=item[1]
|
52 |
|
53 |
# Translate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
def gpt_translate(text,text_id):
|
55 |
text = text.replace("\n"," ")
|
56 |
prompt = args["openai_api_settings"]["prompt_prefix"]+text+args["openai_api_settings"]["prompt_postfix"]
|
57 |
-
translation, if_succ = get_gpt_completion(prompt,
|
58 |
if dic[text_id]["text"].replace("\n"," ") == text and if_succ:
|
59 |
dic[text_id]["gpt3"] = translation
|
60 |
return translation
|
@@ -70,7 +92,7 @@ def baidu_translate(text,text_id):
|
|
70 |
dic[text_id]["baidu"] = translation
|
71 |
return translation
|
72 |
|
73 |
-
def batch_translate(
|
74 |
progress(0, desc="Starting...")
|
75 |
if text_start_id not in id_lis or text_end_id not in id_lis or idx_dic[text_start_id] > idx_dic[text_end_id]:
|
76 |
gr.Warning("找不到指定序号, 或id前后顺序错误")
|
@@ -78,14 +100,9 @@ def batch_translate(radio, check, text_start_id,text_end_id,progress=gr.Progress
|
|
78 |
start = idx_dic[text_start_id]
|
79 |
end = idx_dic[text_end_id] + 1
|
80 |
lis = id_lis[start:end]
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
time.sleep(0.1)
|
85 |
-
if radio == 'Baidu':
|
86 |
-
for key in progress.tqdm(lis):
|
87 |
-
baidu_translate(dic[key]['text'],key)
|
88 |
-
time.sleep(0.1)
|
89 |
if check:
|
90 |
save_json(show_info=False)
|
91 |
gr.Info(f"批量机翻成功, 共完成{end-start}句翻译")
|
@@ -104,7 +121,7 @@ def next_text():
|
|
104 |
id_idx += 1
|
105 |
return id_lis[id_idx]
|
106 |
|
107 |
-
def replace(
|
108 |
if not text_id:
|
109 |
text_id = id_lis[id_idx]
|
110 |
if check_file:
|
@@ -116,33 +133,53 @@ def replace(text_gpt,text_baidu,text_final,text_id, check_file = True):
|
|
116 |
replace_dic[item[0]]=item[1]
|
117 |
f.close()
|
118 |
for key,value in replace_dic.items():
|
119 |
-
|
120 |
-
|
121 |
text_final = text_final.replace(key, value)
|
122 |
-
dic[text_id][
|
123 |
-
dic[text_id][
|
124 |
dic[text_id]["text_CN"] = text_final
|
125 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
-
def change_id(text_id):
|
128 |
if not text_id or text_id not in idx_dic: return args["file_path"],"","","","","",""
|
129 |
global id_idx
|
130 |
id_idx = idx_dic[text_id]
|
131 |
-
if
|
132 |
-
dic[text_id][
|
133 |
-
if
|
134 |
-
dic[text_id][
|
135 |
if "text_CN" not in dic[text_id]:
|
136 |
dic[text_id]["text_CN"] = ""
|
137 |
if dic[text_id]["name"] not in name_dic:
|
138 |
name_dic[dic[text_id]["name"]] = dic[text_id]["name"]
|
139 |
dic[text_id]["name_CN"] = name_dic[dic[text_id]["name"]]
|
140 |
-
replace(dic[text_id][
|
|
|
141 |
if if_save_id_immediately:
|
142 |
args["last_edited_id"] = text_id
|
143 |
save_config(args,config_path)
|
144 |
return args["file_path"],dic[text_id]["text"],dic[text_id]["name"],name_dic[dic[text_id]["name"]],\
|
145 |
-
dic[text_id][
|
146 |
|
147 |
def change_final(text,text_id):
|
148 |
if not text_id or not text_id in idx_dic: return
|
@@ -157,6 +194,9 @@ def change_name(name,name_cn,text_id):
|
|
157 |
dic[text_id]["name_CN"] = name_cn
|
158 |
return
|
159 |
|
|
|
|
|
|
|
160 |
def save_json(show_info = True):
|
161 |
global altered_text_finals
|
162 |
with open(abs_path, "w", encoding ="utf8") as json_file:
|
@@ -191,7 +231,7 @@ def load_last_position(text_path):
|
|
191 |
save_config(args,config_path)
|
192 |
return args["last_edited_id"]
|
193 |
|
194 |
-
def submit_api(baidu_api_id, baidu_api_key, from_lang, to_lang,
|
195 |
global args
|
196 |
if baidu_api_id != "":
|
197 |
args["baidu_api_settings"]["api_id"] = baidu_api_id
|
@@ -201,8 +241,8 @@ def submit_api(baidu_api_id, baidu_api_key, from_lang, to_lang, openai_api_key,p
|
|
201 |
args["baidu_api_settings"]["from_lang"] = from_lang
|
202 |
if to_lang != "":
|
203 |
args["baidu_api_settings"]["to_lang"] = to_lang
|
204 |
-
if
|
205 |
-
args["
|
206 |
args["openai_api_settings"]["prompt_prefix"] = prefix
|
207 |
args["openai_api_settings"]["prompt_postfix"] = postfix
|
208 |
args["target_id"] = target_id
|
@@ -368,23 +408,23 @@ shortcut_js = """
|
|
368 |
<script>
|
369 |
function shortcuts(e) {
|
370 |
|
371 |
-
if (e.key.toLowerCase() == "s" && e.
|
372 |
document.getElementById("button_save").click();
|
373 |
}
|
374 |
-
if (e.key.toLowerCase() == "w" && e.
|
375 |
document.getElementById("button_up").click();
|
376 |
}
|
377 |
-
if (e.key.toLowerCase() == "x" && e.
|
378 |
document.getElementById("button_down").click();
|
379 |
}
|
380 |
-
if (e.key.toLowerCase() == "r" && e.
|
381 |
document.getElementById("button_replace").click();
|
382 |
}
|
383 |
-
if (e.key.toLowerCase() == "
|
384 |
-
document.getElementById("
|
385 |
}
|
386 |
-
if (e.key.toLowerCase() == "
|
387 |
-
document.getElementById("
|
388 |
}
|
389 |
|
390 |
}
|
@@ -393,13 +433,13 @@ document.addEventListener('keyup', shortcuts, false);
|
|
393 |
"""
|
394 |
|
395 |
with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
396 |
-
gr.Markdown("# <center>EasyTranslator v1.0
|
397 |
# 文本编辑页
|
398 |
with gr.Tab("文本编辑"):
|
399 |
gr.Markdown("## 文本编辑及保存区")
|
400 |
with gr.Row():
|
401 |
-
text_file_path = gr.Textbox(label = "File Path", value = args["file_path"])
|
402 |
-
text_id = gr.Textbox(label = "Text id",show_copy_button=True)
|
403 |
button_load_pos = gr.Button("LOAD last edited position")
|
404 |
if not if_save_id_immediately:
|
405 |
button_save_pos = gr.Button("SAVE last edited position")
|
@@ -407,18 +447,21 @@ with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
|
407 |
if not moyu_mode:
|
408 |
# 全屏mode
|
409 |
with gr.Column():
|
410 |
-
text_name = gr.Textbox(label = "Name")
|
411 |
-
text_text = gr.Textbox(label = "Text", lines=10,show_copy_button=True)
|
412 |
-
button_save = gr.Button("SAVE FILE",scale= 2,elem_id = "button_save")
|
|
|
|
|
|
|
413 |
with gr.Column():
|
414 |
-
text_name_cn = gr.Textbox(label = "Name_CN")
|
415 |
with gr.Row():
|
416 |
-
|
417 |
-
|
418 |
with gr.Row():
|
419 |
-
|
420 |
-
|
421 |
-
text_final = gr.Textbox(label = "Text_CN", lines=3,show_copy_button=True,interactive = True)
|
422 |
with gr.Row():
|
423 |
button_up = gr.Button("↑",elem_id = "button_up")
|
424 |
button_down = gr.Button("↓",elem_id = "button_down")
|
@@ -426,32 +469,35 @@ with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
|
426 |
else:
|
427 |
# 摸鱼mode
|
428 |
with gr.Column():
|
429 |
-
|
430 |
-
|
431 |
-
|
|
|
432 |
with gr.Column():
|
433 |
with gr.Row():
|
434 |
-
|
435 |
-
|
436 |
with gr.Row():
|
437 |
-
|
438 |
-
|
439 |
-
text_text = gr.Textbox(label = "Text", lines=3,show_copy_button=True)
|
440 |
-
text_final = gr.Textbox(label = "Text_CN", lines=3,show_copy_button=True,interactive = True)
|
441 |
with gr.Row():
|
442 |
-
button_up = gr.Button("↑")
|
443 |
-
button_down = gr.Button("↓")
|
444 |
-
button_replace = gr.Button("Replace")
|
|
|
|
|
445 |
label_remaining_text = gr.Label(label="进度",value = "目标剩余???条")
|
446 |
gr.Markdown("## 批量机翻区")
|
447 |
with gr.Row():
|
448 |
text_translate_start_id = gr.Textbox(label = "起始句id")
|
449 |
text_translate_end_id = gr.Textbox(label = "结束句id")
|
450 |
with gr.Row():
|
451 |
-
|
452 |
label_progress = gr.Label(label = "进度条",value="")
|
453 |
-
checkbox_if_save_translation = gr.Checkbox(value= False, label = "
|
454 |
-
button_batch_translate = gr.Button("
|
455 |
|
456 |
tab_context = gr.Tab("文本预览及导出")
|
457 |
with tab_context:
|
@@ -459,14 +505,14 @@ with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
|
459 |
with gr.Row():
|
460 |
with gr.Column():
|
461 |
with gr.Row():
|
462 |
-
text_refresh_id = gr.Textbox(label = "
|
463 |
text_context_length = gr.Textbox(label = "上下文长度", value = args["context_half_length"])
|
464 |
radio_context_type = gr.Radio(choices = ["上下文","上文", "下文"], label = "预览模式",value="下文")
|
465 |
with gr.Column():
|
466 |
with gr.Row():
|
467 |
button_refresh = gr.Button("Refresh")
|
468 |
button_save_context = gr.Button("Save Changes")
|
469 |
-
checkbox_if_save_context = gr.Checkbox(value= False, label = "
|
470 |
dataframe_context = gr.DataFrame(headers=['id','name','name_CN','text','text_CN'],
|
471 |
interactive=True)
|
472 |
gr.Markdown("## 文档导出区")
|
@@ -498,9 +544,10 @@ with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
|
498 |
gr.Markdown("## JSON to CSV(支持批量上传)")
|
499 |
with gr.Row():
|
500 |
with gr.Column():
|
501 |
-
file_target_json = gr.File(file_types=["json"],file_count = "multiple",label="Input JSON")
|
502 |
button_convert2csv = gr.Button("Convert")
|
503 |
-
file_result_csv = gr.File(file_types=["
|
|
|
504 |
# 文件合并页
|
505 |
with gr.Tab("文件合并"):
|
506 |
gr.Markdown("## 合并JSON文件")
|
@@ -509,8 +556,8 @@ with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
|
509 |
若起止id顺序颠倒或不存在,按钮不会作用。请仔细检查并做好备份!!")
|
510 |
with gr.Column():
|
511 |
|
512 |
-
text_merged_path = gr.Textbox(label = "File Path", value = args["file_path"])
|
513 |
-
file_merging_json = gr.File(file_types=["json"],file_count = "single", label="File to be merged")
|
514 |
with gr.Row():
|
515 |
text_merge_start_id = gr.Textbox(label="起始句id",value = "")
|
516 |
text_merge_end_id = gr.Textbox(label="结束句id",value = "")
|
@@ -531,28 +578,33 @@ with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
|
531 |
|
532 |
# API设置页
|
533 |
with gr.Tab("API Settings"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
534 |
gr.Markdown("## 百度 API")
|
535 |
-
|
536 |
-
|
537 |
with gr.Row():
|
538 |
text_from_lang = gr.Textbox(label="From Lang",value = args["baidu_api_settings"]["from_lang"])
|
539 |
text_to_lang = gr.Textbox(label="To Lang",value = args["baidu_api_settings"]["to_lang"])
|
540 |
-
gr.Markdown("## OPENAI API")
|
541 |
-
text_openai_api = gr.Textbox(label="OPENAI API Key",value = args["openai_api_settings"]["openai_api_key"])
|
542 |
-
with gr.Row():
|
543 |
-
text_prefix = gr.Textbox(label="Prompt Prefix",value = args["openai_api_settings"]["prompt_prefix"])
|
544 |
-
text_postfix = gr.Textbox(label="Prompt Postfix",value = args["openai_api_settings"]["prompt_postfix"])
|
545 |
-
gr.Markdown("## 目标id")
|
546 |
-
text_target_id = gr.Textbox(label="Target Id",value = args["target_id"])
|
547 |
button_api_submit = gr.Button("Submit")
|
548 |
|
549 |
-
|
550 |
# 标签页行为
|
551 |
tab_context.select(refresh_context, inputs=[text_id,text_context_length,radio_context_type],outputs=[dataframe_context,text_refresh_id])
|
552 |
|
|
|
|
|
|
|
|
|
|
|
553 |
# 文本框行为
|
554 |
-
text_id.change(change_id, inputs = [text_id],
|
555 |
-
outputs = [text_file_path,text_text,text_name,text_name_cn,
|
556 |
text_id.change(get_remaining_text_num,inputs = None, outputs= [label_remaining_text])
|
557 |
text_final.change(change_final,inputs = [text_final,text_id])
|
558 |
text_name_cn.change(change_name,inputs = [text_name,text_name_cn,text_id])
|
@@ -564,16 +616,16 @@ with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
|
564 |
button_save_pos.click(save_last_position, inputs = [text_id])
|
565 |
button_up.click(last_text, outputs = text_id)
|
566 |
button_down.click(next_text, outputs = text_id)
|
567 |
-
|
568 |
-
inputs=[text_text,text_id], outputs=
|
569 |
-
|
570 |
-
inputs=[text_text,text_id], outputs=
|
571 |
button_replace.click(replace,
|
572 |
-
inputs = [
|
573 |
-
outputs=[
|
574 |
button_save.click(save_json)
|
575 |
|
576 |
-
button_batch_translate.click(batch_translate, inputs = [
|
577 |
outputs = [label_progress])
|
578 |
|
579 |
# -预览及导出页
|
@@ -598,8 +650,8 @@ with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
|
598 |
|
599 |
# -API管理页
|
600 |
button_api_submit.click(submit_api,
|
601 |
-
inputs = [
|
602 |
-
|
603 |
|
604 |
demo.queue()
|
605 |
|
|
|
1 |
import gradio as gr
|
2 |
+
import os
|
3 |
from os import path as osp
|
4 |
import json
|
5 |
from utils import *
|
|
|
10 |
# idx指代顺序排列的序号,0,1,2,...
|
11 |
config_path = osp.join(osp.dirname(osp.abspath(__file__)),"./config.json")
|
12 |
args = load_config(config_path)
|
13 |
+
|
14 |
+
model_list = list(MODEL_NAME_DICT.keys()) + ["gpt3","baidu"]
|
15 |
+
for key, value in args["API_KEYS"].items():
|
16 |
+
if "API_KEY" in key and "YOUR" not in value:
|
17 |
+
os.environ[key] = value
|
18 |
+
|
19 |
if_save_id_immediately = True if int(args["if_save_id_immediately"]) else False
|
20 |
moyu_mode = True if int(args["moyu_mode"]) else False
|
21 |
path = args["file_path"]
|
|
|
23 |
replace_dict_path = smart_path(args["replace_dict_path"])
|
24 |
name_dict_path = smart_path(args["name_dict_path"])
|
25 |
altered_text_finals= set()
|
26 |
+
time_limit = int(args["time_limit"]) if "time_limit" in args and isinstance(args["time_limit"],int) else 10
|
27 |
|
28 |
if osp.exists(abs_path):
|
29 |
with open(abs_path, "r", encoding ="utf8") as json_file:
|
|
|
58 |
name_dic[item[0]]=item[1]
|
59 |
|
60 |
# Translate
|
61 |
+
def llm_translate(text, text_id, model_name):
|
62 |
+
if model_name not in model_list:
|
63 |
+
return ""
|
64 |
+
if model_name == "baidu":
|
65 |
+
return baidu_translate(text,text_id)
|
66 |
+
elif model_name == "gpt3":
|
67 |
+
return gpt_translate(text,text_id)
|
68 |
+
text = text.replace("\n"," ")
|
69 |
+
prompt = args["openai_api_settings"]["prompt_prefix"]+text+args["openai_api_settings"]["prompt_postfix"]
|
70 |
+
translation, if_succ = get_llm_completion(prompt, time_limit=int(time_limit), model_name=model_name)
|
71 |
+
if dic[text_id]["text"].replace("\n"," ") == text and if_succ:
|
72 |
+
dic[text_id][model_name] = translation
|
73 |
+
save_config(args,config_path)
|
74 |
+
return translation
|
75 |
+
|
76 |
def gpt_translate(text,text_id):
|
77 |
text = text.replace("\n"," ")
|
78 |
prompt = args["openai_api_settings"]["prompt_prefix"]+text+args["openai_api_settings"]["prompt_postfix"]
|
79 |
+
translation, if_succ = get_gpt_completion(prompt, time_limit=int(time_limit))
|
80 |
if dic[text_id]["text"].replace("\n"," ") == text and if_succ:
|
81 |
dic[text_id]["gpt3"] = translation
|
82 |
return translation
|
|
|
92 |
dic[text_id]["baidu"] = translation
|
93 |
return translation
|
94 |
|
95 |
+
def batch_translate(dropdown_batch_model, check, text_start_id,text_end_id,progress=gr.Progress()):
|
96 |
progress(0, desc="Starting...")
|
97 |
if text_start_id not in id_lis or text_end_id not in id_lis or idx_dic[text_start_id] > idx_dic[text_end_id]:
|
98 |
gr.Warning("找不到指定序号, 或id前后顺序错误")
|
|
|
100 |
start = idx_dic[text_start_id]
|
101 |
end = idx_dic[text_end_id] + 1
|
102 |
lis = id_lis[start:end]
|
103 |
+
for key in progress.tqdm(lis):
|
104 |
+
llm_translate(dic[key]['text'],key,dropdown_batch_model)
|
105 |
+
time.sleep(0.05)
|
|
|
|
|
|
|
|
|
|
|
106 |
if check:
|
107 |
save_json(show_info=False)
|
108 |
gr.Info(f"批量机翻成功, 共完成{end-start}句翻译")
|
|
|
121 |
id_idx += 1
|
122 |
return id_lis[id_idx]
|
123 |
|
124 |
+
def replace(dropbox_model1,dropbox_model2,text_model1,text_model2,text_final,text_id, check_file = True):
|
125 |
if not text_id:
|
126 |
text_id = id_lis[id_idx]
|
127 |
if check_file:
|
|
|
133 |
replace_dic[item[0]]=item[1]
|
134 |
f.close()
|
135 |
for key,value in replace_dic.items():
|
136 |
+
text_model1 = text_model1.replace(key, value)
|
137 |
+
text_model2 = text_model2.replace(key, value)
|
138 |
text_final = text_final.replace(key, value)
|
139 |
+
dic[text_id][dropbox_model1] = text_model1
|
140 |
+
dic[text_id][dropbox_model2] = text_model2
|
141 |
dic[text_id]["text_CN"] = text_final
|
142 |
+
return text_model1,text_model2,text_final
|
143 |
+
|
144 |
+
def change_model_name0(text_id, model_name):
|
145 |
+
# 改变机翻文本框
|
146 |
+
if not text_id or not text_id in idx_dic: return ""
|
147 |
+
if model_name not in model_list: return ""
|
148 |
+
args["selected_model"][0] = model_name
|
149 |
+
if model_name in dic[text_id]:
|
150 |
+
return dic[text_id][model_name]
|
151 |
+
else:
|
152 |
+
return ""
|
153 |
+
def change_model_name1(text_id, model_name):
|
154 |
+
# 改变机翻文本框
|
155 |
+
if not text_id or not text_id in idx_dic: return ""
|
156 |
+
if model_name not in model_list: return ""
|
157 |
+
args["selected_model"][1] = model_name
|
158 |
+
if model_name in dic[text_id]:
|
159 |
+
return dic[text_id][model_name]
|
160 |
+
else:
|
161 |
+
return ""
|
162 |
|
163 |
+
def change_id(text_id, dropbox_model1, dropbox_model2):
|
164 |
if not text_id or text_id not in idx_dic: return args["file_path"],"","","","","",""
|
165 |
global id_idx
|
166 |
id_idx = idx_dic[text_id]
|
167 |
+
if dropbox_model1 not in dic[text_id]:
|
168 |
+
dic[text_id][dropbox_model1] = ""
|
169 |
+
if dropbox_model2 not in dic[text_id]:
|
170 |
+
dic[text_id][dropbox_model2] = ""
|
171 |
if "text_CN" not in dic[text_id]:
|
172 |
dic[text_id]["text_CN"] = ""
|
173 |
if dic[text_id]["name"] not in name_dic:
|
174 |
name_dic[dic[text_id]["name"]] = dic[text_id]["name"]
|
175 |
dic[text_id]["name_CN"] = name_dic[dic[text_id]["name"]]
|
176 |
+
replace(dropbox_model1, dropbox_model2, dic[text_id][dropbox_model1],dic[text_id][dropbox_model2],dic[text_id]["text_CN"],text_id,False)
|
177 |
+
args["selected_model"] = [dropbox_model1, dropbox_model2]
|
178 |
if if_save_id_immediately:
|
179 |
args["last_edited_id"] = text_id
|
180 |
save_config(args,config_path)
|
181 |
return args["file_path"],dic[text_id]["text"],dic[text_id]["name"],name_dic[dic[text_id]["name"]],\
|
182 |
+
dic[text_id][dropbox_model1],dic[text_id][dropbox_model2],dic[text_id]["text_CN"]
|
183 |
|
184 |
def change_final(text,text_id):
|
185 |
if not text_id or not text_id in idx_dic: return
|
|
|
194 |
dic[text_id]["name_CN"] = name_cn
|
195 |
return
|
196 |
|
197 |
+
def change_apikey(dropdown_apikey):
|
198 |
+
return args["API_KEYS"][dropdown_apikey] if dropdown_apikey in args["API_KEYS"] else ""
|
199 |
+
|
200 |
def save_json(show_info = True):
|
201 |
global altered_text_finals
|
202 |
with open(abs_path, "w", encoding ="utf8") as json_file:
|
|
|
231 |
save_config(args,config_path)
|
232 |
return args["last_edited_id"]
|
233 |
|
234 |
+
def submit_api(baidu_api_id, baidu_api_key, from_lang, to_lang, dropdown_apikey,text_apikey,prefix,postfix,target_id):
|
235 |
global args
|
236 |
if baidu_api_id != "":
|
237 |
args["baidu_api_settings"]["api_id"] = baidu_api_id
|
|
|
241 |
args["baidu_api_settings"]["from_lang"] = from_lang
|
242 |
if to_lang != "":
|
243 |
args["baidu_api_settings"]["to_lang"] = to_lang
|
244 |
+
if text_apikey != "":
|
245 |
+
args["API_KEYS"][dropdown_apikey] = text_apikey
|
246 |
args["openai_api_settings"]["prompt_prefix"] = prefix
|
247 |
args["openai_api_settings"]["prompt_postfix"] = postfix
|
248 |
args["target_id"] = target_id
|
|
|
408 |
<script>
|
409 |
function shortcuts(e) {
|
410 |
|
411 |
+
if (e.key.toLowerCase() == "s" && e.altKey) {
|
412 |
document.getElementById("button_save").click();
|
413 |
}
|
414 |
+
if (e.key.toLowerCase() == "w" && e.altKey) {
|
415 |
document.getElementById("button_up").click();
|
416 |
}
|
417 |
+
if (e.key.toLowerCase() == "x" && e.altKey) {
|
418 |
document.getElementById("button_down").click();
|
419 |
}
|
420 |
+
if (e.key.toLowerCase() == "r" && e.altKey) {
|
421 |
document.getElementById("button_replace").click();
|
422 |
}
|
423 |
+
if (e.key.toLowerCase() == "q" && e.altKey) {
|
424 |
+
document.getElementById("button_translate_model1").click();
|
425 |
}
|
426 |
+
if (e.key.toLowerCase() == "e" && e.altKey) {
|
427 |
+
document.getElementById("button_translate_model2").click();
|
428 |
}
|
429 |
|
430 |
}
|
|
|
433 |
"""
|
434 |
|
435 |
with gr.Blocks(theme=Theme1(),head=shortcut_js) as demo:
|
436 |
+
gr.Markdown("# <center>EasyTranslator v1.1.0</center> ",visible=True)
|
437 |
# 文本编辑页
|
438 |
with gr.Tab("文本编辑"):
|
439 |
gr.Markdown("## 文本编辑及保存区")
|
440 |
with gr.Row():
|
441 |
+
text_file_path = gr.Textbox(label = "File Path - 数据文件JSON路径", value = args["file_path"])
|
442 |
+
text_id = gr.Textbox(label = "Text id - 当前文本id",show_copy_button=True)
|
443 |
button_load_pos = gr.Button("LOAD last edited position")
|
444 |
if not if_save_id_immediately:
|
445 |
button_save_pos = gr.Button("SAVE last edited position")
|
|
|
447 |
if not moyu_mode:
|
448 |
# 全屏mode
|
449 |
with gr.Column():
|
450 |
+
text_name = gr.Textbox(label = "Name - 原文人名")
|
451 |
+
text_text = gr.Textbox(label = "Text - 原文文本", lines=10,show_copy_button=True)
|
452 |
+
button_save = gr.Button("SAVE JSON FILE",scale= 2,elem_id = "button_save")
|
453 |
+
dropdown_model1 = gr.Dropdown(choices=model_list,value=args["selected_model"][0], label = "Choose Model1 - 选择模型1",interactive=True)
|
454 |
+
dropdown_model2 = gr.Dropdown(choices=model_list,value=args["selected_model"][1], label = "Choose Model2 - 选择模型2",interactive=True)
|
455 |
+
|
456 |
with gr.Column():
|
457 |
+
text_name_cn = gr.Textbox(label = "Name_CN - 译文人名")
|
458 |
with gr.Row():
|
459 |
+
text_model1 = gr.Textbox(label="Model1 - 模型1译文",lines=3,show_copy_button=True,interactive = True)
|
460 |
+
button_translate_model1 = gr.Button("Translate(Model1)",elem_id = "button_translate_model1")
|
461 |
with gr.Row():
|
462 |
+
text_model2 = gr.Textbox(label="Model2 - 模型2译文",lines=3,show_copy_button=True,interactive = True)
|
463 |
+
button_translate_model2 = gr.Button("Translate(Model2)",elem_id = "button_translate_model2")
|
464 |
+
text_final = gr.Textbox(label = "Text_CN - 人工译文", lines=3,show_copy_button=True,interactive = True)
|
465 |
with gr.Row():
|
466 |
button_up = gr.Button("↑",elem_id = "button_up")
|
467 |
button_down = gr.Button("↓",elem_id = "button_down")
|
|
|
469 |
else:
|
470 |
# 摸鱼mode
|
471 |
with gr.Column():
|
472 |
+
dropdown_model1 = gr.Dropdown(choices=model_list,value=args["selected_model"][0], label = "Choose Model1 - 选择模型1",interactive=True)
|
473 |
+
dropdown_model2 = gr.Dropdown(choices=model_list,value=args["selected_model"][1], label = "Choose Model2 - 选择模型2",interactive=True)
|
474 |
+
text_name = gr.Textbox(label = "Name - 原文人名")
|
475 |
+
text_name_cn = gr.Textbox(label = "Name_CN - 译文人名")
|
476 |
with gr.Column():
|
477 |
with gr.Row():
|
478 |
+
text_model1 = gr.Textbox(label="Model1 - 模型1译文",lines=3,show_copy_button=True,interactive = True)
|
479 |
+
button_translate_model1 = gr.Button("Translate(Model1)",elem_id = "button_translate_model1")
|
480 |
with gr.Row():
|
481 |
+
text_model2 = gr.Textbox(label="Model2 - 模型2译文",lines=3,show_copy_button=True,interactive = True)
|
482 |
+
button_translate_model2 = gr.Button("Translate(Model2)",elem_id = "button_translate_model2")
|
483 |
+
text_text = gr.Textbox(label = "Text - 原文文本", lines=3,show_copy_button=True)
|
484 |
+
text_final = gr.Textbox(label = "Text_CN - 人工译文", lines=3,show_copy_button=True,interactive = True)
|
485 |
with gr.Row():
|
486 |
+
button_up = gr.Button("↑",elem_id = "button_up")
|
487 |
+
button_down = gr.Button("↓",elem_id = "button_down")
|
488 |
+
button_replace = gr.Button("Replace",elem_id = "button_replace")
|
489 |
+
button_save = gr.Button("SAVE JSON FILE",scale= 2,elem_id = "button_save")
|
490 |
+
|
491 |
label_remaining_text = gr.Label(label="进度",value = "目标剩余???条")
|
492 |
gr.Markdown("## 批量机翻区")
|
493 |
with gr.Row():
|
494 |
text_translate_start_id = gr.Textbox(label = "起始句id")
|
495 |
text_translate_end_id = gr.Textbox(label = "结束句id")
|
496 |
with gr.Row():
|
497 |
+
dropdown_model_batch = gr.Dropdown(choices=model_list,value=args["selected_model"][0], label = "批量翻译模型选择",interactive=True)
|
498 |
label_progress = gr.Label(label = "进度条",value="")
|
499 |
+
checkbox_if_save_translation = gr.Checkbox(value= False, label = "翻译完成后直接保存文件")
|
500 |
+
button_batch_translate = gr.Button("开始批量翻译")
|
501 |
|
502 |
tab_context = gr.Tab("文本预览及导出")
|
503 |
with tab_context:
|
|
|
505 |
with gr.Row():
|
506 |
with gr.Column():
|
507 |
with gr.Row():
|
508 |
+
text_refresh_id = gr.Textbox(label = "Text id - 当前文本id", value = args["last_edited_id"])
|
509 |
text_context_length = gr.Textbox(label = "上下文长度", value = args["context_half_length"])
|
510 |
radio_context_type = gr.Radio(choices = ["上下文","上文", "下文"], label = "预览模式",value="下文")
|
511 |
with gr.Column():
|
512 |
with gr.Row():
|
513 |
button_refresh = gr.Button("Refresh")
|
514 |
button_save_context = gr.Button("Save Changes")
|
515 |
+
checkbox_if_save_context = gr.Checkbox(value= False, label = "修改直接存入json文件")
|
516 |
dataframe_context = gr.DataFrame(headers=['id','name','name_CN','text','text_CN'],
|
517 |
interactive=True)
|
518 |
gr.Markdown("## 文档导出区")
|
|
|
544 |
gr.Markdown("## JSON to CSV(支持批量上传)")
|
545 |
with gr.Row():
|
546 |
with gr.Column():
|
547 |
+
file_target_json = gr.File(file_types=[".json"],file_count = "multiple",label="Input JSON")
|
548 |
button_convert2csv = gr.Button("Convert")
|
549 |
+
file_result_csv = gr.File(file_types=[".csv"],label="Output CSV",interactive=False)
|
550 |
+
|
551 |
# 文件合并页
|
552 |
with gr.Tab("文件合并"):
|
553 |
gr.Markdown("## 合并JSON文件")
|
|
|
556 |
若起止id顺序颠倒或不存在,按钮不会作用。请仔细检查并做好备份!!")
|
557 |
with gr.Column():
|
558 |
|
559 |
+
text_merged_path = gr.Textbox(label = "File Path - 被覆盖的文件地址", value = args["file_path"])
|
560 |
+
file_merging_json = gr.File(file_types=["json"],file_count = "single", label="File to be merged - 用于覆盖的文件")
|
561 |
with gr.Row():
|
562 |
text_merge_start_id = gr.Textbox(label="起始句id",value = "")
|
563 |
text_merge_end_id = gr.Textbox(label="结束句id",value = "")
|
|
|
578 |
|
579 |
# API设置页
|
580 |
with gr.Tab("API Settings"):
|
581 |
+
gr.Markdown("## 目标id")
|
582 |
+
text_target_id = gr.Textbox(label="Target Id",value = args["target_id"])
|
583 |
+
gr.Markdown("## API KEY")
|
584 |
+
dropdown_apikey = gr.Dropdown(list(args["API_KEYS"].keys()), value="OPENAI_API_KEY",label = "填写API KEY",interactive=True)
|
585 |
+
text_apikey = gr.Textbox(label="API KEY",value = args["API_KEYS"]["OPENAI_API_KEY"])
|
586 |
+
with gr.Row():
|
587 |
+
text_prefix = gr.Textbox(label="Prompt Prefix",value = args["openai_api_settings"]["prompt_prefix"])
|
588 |
+
text_postfix = gr.Textbox(label="Prompt Postfix",value = args["openai_api_settings"]["prompt_postfix"])
|
589 |
gr.Markdown("## 百度 API")
|
590 |
+
text_model2_api_id = gr.Textbox(label="Baidu API Id",value = args["baidu_api_settings"]["api_id"])
|
591 |
+
text_model2_api_key = gr.Textbox(label="Baidu API Key", value = args["baidu_api_settings"]["api_key"])
|
592 |
with gr.Row():
|
593 |
text_from_lang = gr.Textbox(label="From Lang",value = args["baidu_api_settings"]["from_lang"])
|
594 |
text_to_lang = gr.Textbox(label="To Lang",value = args["baidu_api_settings"]["to_lang"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
595 |
button_api_submit = gr.Button("Submit")
|
596 |
|
|
|
597 |
# 标签页行为
|
598 |
tab_context.select(refresh_context, inputs=[text_id,text_context_length,radio_context_type],outputs=[dataframe_context,text_refresh_id])
|
599 |
|
600 |
+
# 下拉选框行为
|
601 |
+
dropdown_model1.change(change_model_name0, inputs = [text_id,dropdown_model1], outputs=[text_model1])
|
602 |
+
dropdown_model2.change(change_model_name1, inputs = [text_id,dropdown_model2], outputs=[text_model2])
|
603 |
+
dropdown_apikey.change(change_apikey, inputs=[dropdown_apikey], outputs=[text_apikey])
|
604 |
+
|
605 |
# 文本框行为
|
606 |
+
text_id.change(change_id, inputs = [text_id,dropdown_model1,dropdown_model2],
|
607 |
+
outputs = [text_file_path,text_text,text_name,text_name_cn,text_model1,text_model2,text_final])
|
608 |
text_id.change(get_remaining_text_num,inputs = None, outputs= [label_remaining_text])
|
609 |
text_final.change(change_final,inputs = [text_final,text_id])
|
610 |
text_name_cn.change(change_name,inputs = [text_name,text_name_cn,text_id])
|
|
|
616 |
button_save_pos.click(save_last_position, inputs = [text_id])
|
617 |
button_up.click(last_text, outputs = text_id)
|
618 |
button_down.click(next_text, outputs = text_id)
|
619 |
+
button_translate_model1.click(llm_translate,
|
620 |
+
inputs=[text_text, text_id, dropdown_model1], outputs=text_model1)
|
621 |
+
button_translate_model2.click(llm_translate,
|
622 |
+
inputs=[text_text, text_id, dropdown_model2], outputs=text_model2)
|
623 |
button_replace.click(replace,
|
624 |
+
inputs = [dropdown_model1,dropdown_model2,text_model1,text_model2,text_final,text_id],
|
625 |
+
outputs=[text_model1,text_model2,text_final])
|
626 |
button_save.click(save_json)
|
627 |
|
628 |
+
button_batch_translate.click(batch_translate, inputs = [dropdown_model_batch,checkbox_if_save_translation,text_translate_start_id,text_translate_end_id],
|
629 |
outputs = [label_progress])
|
630 |
|
631 |
# -预览及导出页
|
|
|
650 |
|
651 |
# -API管理页
|
652 |
button_api_submit.click(submit_api,
|
653 |
+
inputs = [text_model2_api_id,text_model2_api_key,text_from_lang,text_to_lang,
|
654 |
+
dropdown_apikey,text_apikey,text_prefix,text_postfix,text_target_id])
|
655 |
|
656 |
demo.queue()
|
657 |
|
config.json
CHANGED
@@ -1,30 +1,43 @@
|
|
1 |
{
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
{
|
2 |
+
"moyu_mode": "1",
|
3 |
+
"if_save_id_immediately": "1",
|
4 |
+
"last_edited_id": "100001002",
|
5 |
+
"target_id": "100001005",
|
6 |
+
"file_path": "./example_text.json",
|
7 |
+
"context_half_length": "10",
|
8 |
+
"name_dict_path": "./example_name_dict.json",
|
9 |
+
"replace_dict_path": "./example_replace_dict.json",
|
10 |
+
"output_txt_path": "./output.txt",
|
11 |
+
"seperator_long": "===============================",
|
12 |
+
"seperator_short": "---------------------",
|
13 |
+
"csv_column_name": {
|
14 |
+
"id": "",
|
15 |
+
"text": "text",
|
16 |
+
"name": "name"
|
17 |
+
},
|
18 |
+
"selected_model": [
|
19 |
+
"baidu",
|
20 |
+
"gpt3"
|
21 |
+
],
|
22 |
+
"baidu_api_settings": {
|
23 |
+
"api_id": "YOUR BAIDU API ID",
|
24 |
+
"api_key": "YOUR BAIDU API KEY",
|
25 |
+
"from_lang": "jp",
|
26 |
+
"to_lang": "zh"
|
27 |
+
},
|
28 |
+
"openai_api_settings": {
|
29 |
+
"openai_api_key": "YOUR OPENAI API KEY",
|
30 |
+
"prompt_prefix": "将以下文字翻译为中文:",
|
31 |
+
"prompt_postfix": "",
|
32 |
+
"time_limit": 15
|
33 |
+
},
|
34 |
+
"API_KEYS": {
|
35 |
+
"OPENAI_API_KEY": "YOUR OPENAI API KEY (https://platform.openai.com/docs/overview)",
|
36 |
+
"GEMINI_API_KEY": "YOUR GEMINI API KEY (https://ai.google.dev/gemini-api/)",
|
37 |
+
"DASHSCOPE_API_KEY": "YOUR QWEN API KEY (https://help.aliyun.com/zh/model-studio/)",
|
38 |
+
"DEEPSEEK_API_KEY": "YOUR DEEPSEEK API KEY (https://api-docs.deepseek.com/)",
|
39 |
+
"ANTHROPIC_API_KEY": "YOUR CLAUDE API KEY (https://www.anthropic.com/api)",
|
40 |
+
"ARK_API_KEY": "YOUR DOUBAO API KEY (https://www.volcengine.com/product/doubao)",
|
41 |
+
"OPENROUTER_API_KEY": "YOUR OPENROUTER API KEY (https://openrouter.ai/)"
|
42 |
+
}
|
43 |
+
}
|
requirements.txt
CHANGED
@@ -1 +1,2 @@
|
|
1 |
-
|
|
|
|
1 |
+
gradio>=5.16.0
|
2 |
+
openai>=1.63.0
|
themes.py
CHANGED
@@ -46,9 +46,8 @@ class Theme1(Base):
|
|
46 |
super().set(
|
47 |
input_background_fill="*neutral_100",
|
48 |
block_title_text_weight="600",
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
# button_secondary_background_fill_hover="*neutral_300",
|
53 |
)
|
54 |
|
|
|
46 |
super().set(
|
47 |
input_background_fill="*neutral_100",
|
48 |
block_title_text_weight="600",
|
49 |
+
block_border_width="3px",
|
50 |
+
button_large_padding="32px",
|
51 |
+
button_secondary_background_fill_hover="*neutral_300",
|
|
|
52 |
)
|
53 |
|