Upload 204 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- group_tags/.gitignore +3 -0
- group_tags/de_DE.yaml +0 -0
- group_tags/default.yaml +0 -0
- group_tags/es_ES.yaml +0 -0
- group_tags/fr_FR.yaml +0 -0
- group_tags/it_IT.yaml +0 -0
- group_tags/ja_JP.yaml +0 -0
- group_tags/ko_KR.yaml +0 -0
- group_tags/pt_PT.yaml +0 -0
- group_tags/ru_RU.yaml +0 -0
- group_tags/zh_CN.yaml +0 -0
- group_tags/zh_HK.yaml +0 -0
- group_tags/zh_TW.yaml +0 -0
- i18n.json +0 -0
- install.py +28 -0
- javascript/main.entry.js +0 -0
- javascript/main.entry.js.map +0 -0
- models/.gitignore +2 -0
- scripts/on_app_started.py +388 -0
- scripts/physton_prompt/csv.py +37 -0
- scripts/physton_prompt/gen_openai.py +19 -0
- scripts/physton_prompt/get_extensions.py +12 -0
- scripts/physton_prompt/get_extra_networks.py +67 -0
- scripts/physton_prompt/get_group_tags.py +43 -0
- scripts/physton_prompt/get_i18n.py +16 -0
- scripts/physton_prompt/get_lang.py +47 -0
- scripts/physton_prompt/get_token_counter.py +23 -0
- scripts/physton_prompt/get_translate_apis.py +123 -0
- scripts/physton_prompt/get_version.py +88 -0
- scripts/physton_prompt/history.py +164 -0
- scripts/physton_prompt/mbart50.py +67 -0
- scripts/physton_prompt/packages.py +49 -0
- scripts/physton_prompt/storage.py +177 -0
- scripts/physton_prompt/styles.py +57 -0
- scripts/physton_prompt/translate.py +150 -0
- scripts/physton_prompt/translator/alibaba_translator.py +95 -0
- scripts/physton_prompt/translator/amazon_translator.py +28 -0
- scripts/physton_prompt/translator/baidu_translator.py +55 -0
- scripts/physton_prompt/translator/base_tanslator.py +87 -0
- scripts/physton_prompt/translator/caiyun_translator.py +40 -0
- scripts/physton_prompt/translator/deepl_translator.py +46 -0
- scripts/physton_prompt/translator/google_tanslator.py +32 -0
- scripts/physton_prompt/translator/iflytekV1_translator.py +113 -0
- scripts/physton_prompt/translator/iflytekV2_translator.py +128 -0
- scripts/physton_prompt/translator/mbart50_translator.py +27 -0
- scripts/physton_prompt/translator/microsoft_translator.py +56 -0
- scripts/physton_prompt/translator/mymemory_translator.py +37 -0
- scripts/physton_prompt/translator/niutrans_translator.py +35 -0
- scripts/physton_prompt/translator/openai_translator.py +60 -0
- scripts/physton_prompt/translator/tencent_translator.py +128 -0
group_tags/.gitignore
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
custom.yaml
|
2 |
+
prepend.yaml
|
3 |
+
append.yaml
|
group_tags/de_DE.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/default.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/es_ES.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/fr_FR.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/it_IT.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/ja_JP.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/ko_KR.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/pt_PT.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/ru_RU.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/zh_CN.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/zh_HK.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
group_tags/zh_TW.yaml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
i18n.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
install.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import launch
|
2 |
+
|
3 |
+
packages = {
|
4 |
+
"chardet": "chardet",
|
5 |
+
"fastapi": "fastapi",
|
6 |
+
"execjs": "PyExecJS",
|
7 |
+
"lxml": "lxml",
|
8 |
+
"tqdm": "tqdm",
|
9 |
+
"pathos": "pathos",
|
10 |
+
"cryptography": "cryptography",
|
11 |
+
|
12 |
+
# The following packages are required for translation service. If you do not need translation service, you can remove them.
|
13 |
+
# 以下是翻译所需的包,如果不需要翻译服务,可以删除掉它们。
|
14 |
+
"openai": "openai",
|
15 |
+
"boto3": "boto3",
|
16 |
+
"aliyunsdkcore": "aliyun-python-sdk-core",
|
17 |
+
"aliyunsdkalimt": "aliyun-python-sdk-alimt",
|
18 |
+
}
|
19 |
+
|
20 |
+
if __name__ == "__main__":
|
21 |
+
for package_name in packages:
|
22 |
+
package = packages[package_name]
|
23 |
+
try:
|
24 |
+
if not launch.is_installed(package_name):
|
25 |
+
launch.run_pip(f"install {package}", f"sd-webui-prompt-all-in-one: {package_name}")
|
26 |
+
except Exception as e:
|
27 |
+
print(e)
|
28 |
+
print(f'Warning: Failed to install {package}, some preprocessors may not work.')
|
javascript/main.entry.js
ADDED
The diff for this file is too large to render.
See raw diff
|
|
javascript/main.entry.js.map
ADDED
The diff for this file is too large to render.
See raw diff
|
|
models/.gitignore
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
*
|
2 |
+
!.gitignore
|
scripts/on_app_started.py
ADDED
@@ -0,0 +1,388 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import os
|
3 |
+
import sys
|
4 |
+
from pathlib import Path
|
5 |
+
from modules import script_callbacks, extra_networks, prompt_parser
|
6 |
+
from fastapi import FastAPI, Body, Request, Response
|
7 |
+
from fastapi.responses import FileResponse
|
8 |
+
from scripts.physton_prompt.storage import Storage
|
9 |
+
from scripts.physton_prompt.get_extensions import get_extensions
|
10 |
+
from scripts.physton_prompt.get_token_counter import get_token_counter
|
11 |
+
from scripts.physton_prompt.get_i18n import get_i18n
|
12 |
+
from scripts.physton_prompt.get_translate_apis import get_translate_apis, privacy_translate_api_config, unprotected_translate_api_config
|
13 |
+
from scripts.physton_prompt.translate import translate
|
14 |
+
from scripts.physton_prompt.history import History
|
15 |
+
from scripts.physton_prompt.csv import get_csvs, get_csv
|
16 |
+
from scripts.physton_prompt.styles import get_style_full_path, get_extension_css_list
|
17 |
+
from scripts.physton_prompt.get_extra_networks import get_extra_networks
|
18 |
+
from scripts.physton_prompt.packages import get_packages_state, install_package
|
19 |
+
from scripts.physton_prompt.gen_openai import gen_openai
|
20 |
+
from scripts.physton_prompt.get_lang import get_lang
|
21 |
+
from scripts.physton_prompt.get_version import get_git_commit_version, get_git_remote_versions, get_latest_version
|
22 |
+
from scripts.physton_prompt.mbart50 import initialize as mbart50_initialize, translate as mbart50_translate
|
23 |
+
from scripts.physton_prompt.get_group_tags import get_group_tags
|
24 |
+
|
25 |
+
try:
|
26 |
+
from modules.shared import cmd_opts
|
27 |
+
|
28 |
+
if cmd_opts.data_dir:
|
29 |
+
extension_dir = os.path.dirname(os.path.abspath(__file__)) + '/../'
|
30 |
+
extension_dir = os.path.normpath(extension_dir) + os.path.sep
|
31 |
+
data_dir = os.path.normpath(cmd_opts.data_dir) + os.path.sep
|
32 |
+
webui_dir = os.path.normpath(Path().absolute()) + os.path.sep
|
33 |
+
if not extension_dir.startswith(webui_dir):
|
34 |
+
find = False
|
35 |
+
if cmd_opts.gradio_allowed_path:
|
36 |
+
for path in cmd_opts.gradio_allowed_path:
|
37 |
+
path = os.path.normpath(path) + os.path.sep
|
38 |
+
if path == extension_dir:
|
39 |
+
find = path
|
40 |
+
break
|
41 |
+
elif extension_dir.startswith(path):
|
42 |
+
find = path
|
43 |
+
break
|
44 |
+
else:
|
45 |
+
pass
|
46 |
+
if not find:
|
47 |
+
message = f'''
|
48 |
+
\033[1;31m[sd-webui-prompt-all-in-one]
|
49 |
+
As you have set the --data-dir parameter and have not added the extension path to the --gradio-allowed-path parameter, the extension may not function properly. Please add the following startup parameter:
|
50 |
+
由于你设置了 --data-dir 参数,并且没有将本扩展路径加入到 --gradio-allowed-path 参数中,所以本扩展可能无法正常运行。请添加启动参数:
|
51 |
+
\033[1;32m--gradio-allowed-path="{extension_dir}"
|
52 |
+
\033[0m
|
53 |
+
'''
|
54 |
+
print(message)
|
55 |
+
except Exception as e:
|
56 |
+
pass
|
57 |
+
|
58 |
+
|
59 |
+
def on_app_started(_: gr.Blocks, app: FastAPI):
|
60 |
+
st = Storage()
|
61 |
+
hi = History()
|
62 |
+
|
63 |
+
@app.get("/physton_prompt/get_version")
|
64 |
+
async def _get_version():
|
65 |
+
return {
|
66 |
+
'version': get_git_commit_version(),
|
67 |
+
'latest_version': get_latest_version(),
|
68 |
+
}
|
69 |
+
|
70 |
+
@app.get("/physton_prompt/get_remote_versions")
|
71 |
+
async def _get_remote_versions(page: int = 1, per_page: int = 100):
|
72 |
+
return {
|
73 |
+
'versions': get_git_remote_versions(page, per_page),
|
74 |
+
}
|
75 |
+
|
76 |
+
@app.get("/physton_prompt/get_config")
|
77 |
+
async def _get_config():
|
78 |
+
return {
|
79 |
+
'i18n': get_i18n(True),
|
80 |
+
'translate_apis': get_translate_apis(True),
|
81 |
+
'packages_state': get_packages_state(),
|
82 |
+
'python': sys.executable,
|
83 |
+
}
|
84 |
+
|
85 |
+
@app.post("/physton_prompt/install_package")
|
86 |
+
async def _install_package(request: Request):
|
87 |
+
data = await request.json()
|
88 |
+
if 'name' not in data:
|
89 |
+
return {"result": get_lang('is_required', {'0': 'name'})}
|
90 |
+
if 'package' not in data:
|
91 |
+
return {"result": get_lang('is_required', {'0': 'package'})}
|
92 |
+
return {"result": install_package(data['name'], data['package'])}
|
93 |
+
|
94 |
+
@app.get("/physton_prompt/get_extensions")
|
95 |
+
async def _get_extensions():
|
96 |
+
return {"extends": get_extensions()}
|
97 |
+
|
98 |
+
@app.post("/physton_prompt/token_counter")
|
99 |
+
async def _token_counter(request: Request):
|
100 |
+
data = await request.json()
|
101 |
+
if 'text' not in data:
|
102 |
+
return {"result": get_lang('is_required', {'0': 'text'})}
|
103 |
+
if 'steps' not in data:
|
104 |
+
return {"result": get_lang('is_required', {'0': 'steps'})}
|
105 |
+
return get_token_counter(data['text'], data['steps'])
|
106 |
+
|
107 |
+
@app.get("/physton_prompt/get_data")
|
108 |
+
async def _get_data(key: str):
|
109 |
+
data = st.get(key)
|
110 |
+
data = privacy_translate_api_config(key, data)
|
111 |
+
return {"data": data}
|
112 |
+
|
113 |
+
@app.get("/physton_prompt/get_datas")
|
114 |
+
async def _get_datas(keys: str):
|
115 |
+
keys = keys.split(',')
|
116 |
+
datas = {}
|
117 |
+
for key in keys:
|
118 |
+
datas[key] = st.get(key)
|
119 |
+
datas[key] = privacy_translate_api_config(key, datas[key])
|
120 |
+
return {"datas": datas}
|
121 |
+
|
122 |
+
@app.post("/physton_prompt/set_data")
|
123 |
+
async def _set_data(request: Request):
|
124 |
+
data = await request.json()
|
125 |
+
if 'key' not in data:
|
126 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'key'})}
|
127 |
+
if 'data' not in data:
|
128 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'data'})}
|
129 |
+
data['data'] = unprotected_translate_api_config(data['key'], data['data'])
|
130 |
+
st.set(data['key'], data['data'])
|
131 |
+
return {"success": True}
|
132 |
+
|
133 |
+
@app.post("/physton_prompt/set_datas")
|
134 |
+
async def _set_datas(request: Request):
|
135 |
+
data = await request.json()
|
136 |
+
if not isinstance(data, dict):
|
137 |
+
return {"success": False, "message": get_lang('is_not_dict', {'0': 'data'})}
|
138 |
+
for key in data:
|
139 |
+
data[key] = unprotected_translate_api_config(key, data[key])
|
140 |
+
st.set(key, data[key])
|
141 |
+
return {"success": True}
|
142 |
+
|
143 |
+
@app.get("/physton_prompt/get_data_list_item")
|
144 |
+
async def _get_data_list_item(key: str, index: int):
|
145 |
+
return {"item": st.list_get(key, index)}
|
146 |
+
|
147 |
+
@app.post("/physton_prompt/push_data_list")
|
148 |
+
async def _push_data_list(request: Request):
|
149 |
+
data = await request.json()
|
150 |
+
if 'key' not in data:
|
151 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'key'})}
|
152 |
+
if 'item' not in data:
|
153 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'item'})}
|
154 |
+
st.list_push(data['key'], data['item'])
|
155 |
+
return {"success": True}
|
156 |
+
|
157 |
+
@app.post("/physton_prompt/pop_data_list")
|
158 |
+
async def _pop_data_list(request: Request):
|
159 |
+
data = await request.json()
|
160 |
+
if 'key' not in data:
|
161 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'key'})}
|
162 |
+
return {"success": True, 'item': st.list_pop(data['key'])}
|
163 |
+
|
164 |
+
@app.post("/physton_prompt/shift_data_list")
|
165 |
+
async def _shift_data_list(request: Request):
|
166 |
+
data = await request.json()
|
167 |
+
if 'key' not in data:
|
168 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'key'})}
|
169 |
+
return {"success": True, 'item': st.list_shift(data['key'])}
|
170 |
+
|
171 |
+
@app.post("/physton_prompt/remove_data_list")
|
172 |
+
async def _remove_data_list(request: Request):
|
173 |
+
data = await request.json()
|
174 |
+
if 'key' not in data:
|
175 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'key'})}
|
176 |
+
if 'index' not in data:
|
177 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'index'})}
|
178 |
+
st.list_remove(data['key'], data['index'])
|
179 |
+
return {"success": True}
|
180 |
+
|
181 |
+
@app.post("/physton_prompt/clear_data_list")
|
182 |
+
async def _clear_data_list(request: Request):
|
183 |
+
data = await request.json()
|
184 |
+
if 'key' not in data:
|
185 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'key'})}
|
186 |
+
st.list_clear(data['key'])
|
187 |
+
return {"success": True}
|
188 |
+
|
189 |
+
@app.get("/physton_prompt/get_histories")
|
190 |
+
async def _get_histories(type: str):
|
191 |
+
return {"histories": hi.get_histories(type)}
|
192 |
+
|
193 |
+
@app.get("/physton_prompt/get_favorites")
|
194 |
+
async def _get_favorites(type: str):
|
195 |
+
return {"favorites": hi.get_favorites(type)}
|
196 |
+
|
197 |
+
@app.post("/physton_prompt/push_history")
|
198 |
+
async def _push_history(request: Request):
|
199 |
+
data = await request.json()
|
200 |
+
if 'type' not in data:
|
201 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
202 |
+
if 'tags' not in data:
|
203 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'tags'})}
|
204 |
+
if 'prompt' not in data:
|
205 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'prompt'})}
|
206 |
+
hi.push_history(data['type'], data['tags'], data['prompt'], data.get('name', ''))
|
207 |
+
return {"success": True}
|
208 |
+
|
209 |
+
@app.post("/physton_prompt/push_favorite")
|
210 |
+
async def _push_favorite(request: Request):
|
211 |
+
data = await request.json()
|
212 |
+
if 'type' not in data:
|
213 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
214 |
+
if 'tags' not in data:
|
215 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'tags'})}
|
216 |
+
if 'prompt' not in data:
|
217 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'prompt'})}
|
218 |
+
hi.push_favorite(data['type'], data['tags'], data['prompt'], data.get('name', ''))
|
219 |
+
return {"success": True}
|
220 |
+
|
221 |
+
@app.get("/physton_prompt/get_latest_history")
|
222 |
+
async def _get_latest_history(type: str):
|
223 |
+
return {"history": hi.get_latest_history(type)}
|
224 |
+
|
225 |
+
@app.post("/physton_prompt/set_history")
|
226 |
+
async def _set_history(request: Request):
|
227 |
+
data = await request.json()
|
228 |
+
if 'type' not in data:
|
229 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
230 |
+
if 'id' not in data:
|
231 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'id'})}
|
232 |
+
if 'tags' not in data:
|
233 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'tags'})}
|
234 |
+
if 'prompt' not in data:
|
235 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'prompt'})}
|
236 |
+
if 'name' not in data:
|
237 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'name'})}
|
238 |
+
return {"success": hi.set_history(data['type'], data['id'], data['tags'], data['prompt'], data['name'])}
|
239 |
+
|
240 |
+
@app.post("/physton_prompt/set_history_name")
|
241 |
+
async def _set_history_name(request: Request):
|
242 |
+
data = await request.json()
|
243 |
+
if 'type' not in data:
|
244 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
245 |
+
if 'id' not in data:
|
246 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'id'})}
|
247 |
+
if 'name' not in data:
|
248 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'name'})}
|
249 |
+
return {"success": hi.set_history_name(data['type'], data['id'], data['name'])}
|
250 |
+
|
251 |
+
@app.post("/physton_prompt/set_favorite_name")
|
252 |
+
async def _set_favorite_name(request: Request):
|
253 |
+
data = await request.json()
|
254 |
+
if 'type' not in data:
|
255 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
256 |
+
if 'id' not in data:
|
257 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'id'})}
|
258 |
+
if 'name' not in data:
|
259 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'name'})}
|
260 |
+
return {"success": hi.set_favorite_name(data['type'], data['id'], data['name'])}
|
261 |
+
|
262 |
+
@app.post("/physton_prompt/dofavorite")
|
263 |
+
async def _dofavorite(request: Request):
|
264 |
+
data = await request.json()
|
265 |
+
if 'type' not in data:
|
266 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
267 |
+
if 'id' not in data:
|
268 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'id'})}
|
269 |
+
return {"success": hi.dofavorite(data['type'], data['id'])}
|
270 |
+
|
271 |
+
@app.post("/physton_prompt/unfavorite")
|
272 |
+
async def _unfavorite(request: Request):
|
273 |
+
data = await request.json()
|
274 |
+
if 'type' not in data:
|
275 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
276 |
+
if 'id' not in data:
|
277 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'id'})}
|
278 |
+
return {"success": hi.unfavorite(data['type'], data['id'])}
|
279 |
+
|
280 |
+
@app.post("/physton_prompt/delete_history")
|
281 |
+
async def _delete_history(request: Request):
|
282 |
+
data = await request.json()
|
283 |
+
if 'type' not in data:
|
284 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
285 |
+
if 'id' not in data:
|
286 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'id'})}
|
287 |
+
return {"success": hi.remove_history(data['type'], data['id'])}
|
288 |
+
|
289 |
+
@app.post("/physton_prompt/delete_histories")
|
290 |
+
async def _delete_histories(request: Request):
|
291 |
+
data = await request.json()
|
292 |
+
if 'type' not in data:
|
293 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'type'})}
|
294 |
+
return {"success": hi.remove_histories(data['type'])}
|
295 |
+
|
296 |
+
@app.post("/physton_prompt/translate")
|
297 |
+
async def _translate(request: Request):
|
298 |
+
data = await request.json()
|
299 |
+
if 'text' not in data:
|
300 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'text'})}
|
301 |
+
if 'from_lang' not in data:
|
302 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'from_lang'})}
|
303 |
+
if 'to_lang' not in data:
|
304 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'to_lang'})}
|
305 |
+
if 'api' not in data:
|
306 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'api'})}
|
307 |
+
if 'api_config' not in data:
|
308 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'api_config'})}
|
309 |
+
return translate(data['text'], data['from_lang'], data['to_lang'], data['api'], data['api_config'])
|
310 |
+
|
311 |
+
@app.post("/physton_prompt/translates")
|
312 |
+
async def _translates(request: Request):
|
313 |
+
data = await request.json()
|
314 |
+
if 'texts' not in data:
|
315 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'texts'})}
|
316 |
+
if 'from_lang' not in data:
|
317 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'from_lang'})}
|
318 |
+
if 'to_lang' not in data:
|
319 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'to_lang'})}
|
320 |
+
if 'api' not in data:
|
321 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'api'})}
|
322 |
+
if 'api_config' not in data:
|
323 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'api_config'})}
|
324 |
+
return translate(data['texts'], data['from_lang'], data['to_lang'], data['api'], data['api_config'])
|
325 |
+
|
326 |
+
@app.get("/physton_prompt/get_csvs")
|
327 |
+
async def _get_csvs():
|
328 |
+
return {"csvs": get_csvs()}
|
329 |
+
|
330 |
+
@app.get("/physton_prompt/get_csv")
|
331 |
+
async def _get_csv(key: str):
|
332 |
+
file = get_csv(key)
|
333 |
+
if not file:
|
334 |
+
return Response(status_code=404)
|
335 |
+
return FileResponse(file, media_type='text/csv', filename=os.path.basename(file))
|
336 |
+
|
337 |
+
@app.get("/physton_prompt/styles")
|
338 |
+
async def _styles(file: str):
|
339 |
+
file_path = get_style_full_path(file)
|
340 |
+
if not os.path.exists(file_path):
|
341 |
+
return Response(status_code=404)
|
342 |
+
return FileResponse(file_path, filename=os.path.basename(file_path))
|
343 |
+
|
344 |
+
@app.get("/physton_prompt/get_extension_css_list")
|
345 |
+
async def _get_extension_css_list():
|
346 |
+
return {"css_list": get_extension_css_list()}
|
347 |
+
|
348 |
+
@app.get("/physton_prompt/get_extra_networks")
|
349 |
+
async def _get_extra_networks():
|
350 |
+
return {"extra_networks": get_extra_networks()}
|
351 |
+
|
352 |
+
@app.post("/physton_prompt/gen_openai")
|
353 |
+
async def _gen_openai(request: Request):
|
354 |
+
data = await request.json()
|
355 |
+
if 'messages' not in data:
|
356 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'messages'})}
|
357 |
+
if 'api_config' not in data:
|
358 |
+
return {"success": False, "message": get_lang('is_required', {'0': 'api_config'})}
|
359 |
+
try:
|
360 |
+
return {"success": True, 'result': gen_openai(data['messages'], data['api_config'])}
|
361 |
+
except Exception as e:
|
362 |
+
return {"success": False, 'message': str(e)}
|
363 |
+
|
364 |
+
@app.post("/physton_prompt/mbart50_initialize")
|
365 |
+
async def _mbart50_initialize(request: Request):
|
366 |
+
try:
|
367 |
+
mbart50_initialize(True)
|
368 |
+
return {"success": True}
|
369 |
+
except Exception as e:
|
370 |
+
return {"success": False, 'message': str(e)}
|
371 |
+
|
372 |
+
@app.get("/physton_prompt/get_group_tags")
|
373 |
+
async def _get_group_tags(lang: str):
|
374 |
+
return {"tags": get_group_tags(lang)}
|
375 |
+
|
376 |
+
try:
|
377 |
+
translate_api = st.get('translateApi')
|
378 |
+
if translate_api == 'mbart50':
|
379 |
+
mbart50_initialize()
|
380 |
+
except Exception:
|
381 |
+
pass
|
382 |
+
|
383 |
+
|
384 |
+
try:
|
385 |
+
script_callbacks.on_app_started(on_app_started)
|
386 |
+
print('sd-webui-prompt-all-in-one background API service started successfully.')
|
387 |
+
except Exception as e:
|
388 |
+
print(f'sd-webui-prompt-all-in-one background API service failed to start: {e}')
|
scripts/physton_prompt/csv.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from pathlib import Path
|
3 |
+
|
4 |
+
base_dir = str(Path().absolute())
|
5 |
+
dirs = [
|
6 |
+
os.path.join(base_dir, 'extensions', 'sd-webui-prompt-all-in-one', 'tags'),
|
7 |
+
os.path.join(base_dir, 'extensions', 'a1111-sd-webui-tagcomplete', 'tags'),
|
8 |
+
]
|
9 |
+
|
10 |
+
|
11 |
+
def get_csvs():
|
12 |
+
global base_dir
|
13 |
+
csvs = []
|
14 |
+
for dir in dirs:
|
15 |
+
if not os.path.exists(dir):
|
16 |
+
continue
|
17 |
+
for file in os.listdir(dir):
|
18 |
+
if file.endswith('.csv'):
|
19 |
+
path = os.path.join(dir, file)
|
20 |
+
name = os.path.basename(file)
|
21 |
+
size = os.path.getsize(path)
|
22 |
+
# 去除 base_dir 后的路径
|
23 |
+
key = path.replace(base_dir, '')
|
24 |
+
csvs.append({
|
25 |
+
'key': key,
|
26 |
+
'name': name,
|
27 |
+
'size': size,
|
28 |
+
'path': path
|
29 |
+
})
|
30 |
+
return csvs
|
31 |
+
|
32 |
+
|
33 |
+
def get_csv(key):
|
34 |
+
path = base_dir + key
|
35 |
+
if not os.path.exists(path):
|
36 |
+
return None
|
37 |
+
return path
|
scripts/physton_prompt/gen_openai.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.get_lang import get_lang
|
2 |
+
from scripts.physton_prompt.get_translate_apis import unprotected_translate_api_config
|
3 |
+
|
4 |
+
|
5 |
+
def gen_openai(messages, api_config):
|
6 |
+
import openai
|
7 |
+
api_config = unprotected_translate_api_config('chatgpt_key', api_config)
|
8 |
+
openai.api_base = api_config.get('api_base', 'https://api.openai.com/v1')
|
9 |
+
openai.api_key = api_config.get('api_key', '')
|
10 |
+
model = api_config.get('model', 'gpt-3.5-turbo')
|
11 |
+
if not openai.api_key:
|
12 |
+
raise Exception(get_lang('is_required', {'0': 'API Key'}))
|
13 |
+
if not messages or len(messages) == 0:
|
14 |
+
raise Exception(get_lang('is_required', {'0': 'messages'}))
|
15 |
+
completion = openai.ChatCompletion.create(model=model, messages=messages, timeout=60)
|
16 |
+
if len(completion.choices) == 0:
|
17 |
+
raise Exception(get_lang('no_response_from', {'0': 'OpenAI'}))
|
18 |
+
content = completion.choices[0].message.content
|
19 |
+
return content
|
scripts/physton_prompt/get_extensions.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from pathlib import Path
|
3 |
+
|
4 |
+
|
5 |
+
def get_extensions():
|
6 |
+
extends_dir = os.path.join(Path().absolute(), 'extensions')
|
7 |
+
extends = []
|
8 |
+
for name in os.listdir(extends_dir):
|
9 |
+
path = os.path.join(extends_dir, name)
|
10 |
+
if os.path.isdir(path):
|
11 |
+
extends.append(name)
|
12 |
+
return extends
|
scripts/physton_prompt/get_extra_networks.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: UTF-8 -*-
|
2 |
+
|
3 |
+
from modules import script_callbacks, extra_networks, prompt_parser, shared, ui_extra_networks
|
4 |
+
import json
|
5 |
+
import os
|
6 |
+
|
7 |
+
filters = [
|
8 |
+
'filename',
|
9 |
+
'description',
|
10 |
+
'search_term',
|
11 |
+
'local_preview',
|
12 |
+
'metadata',
|
13 |
+
]
|
14 |
+
|
15 |
+
|
16 |
+
def get_extra_networks():
|
17 |
+
result = []
|
18 |
+
try:
|
19 |
+
for extra_page in ui_extra_networks.extra_pages:
|
20 |
+
result_item = {
|
21 |
+
'name': extra_page.name,
|
22 |
+
'title': extra_page.title,
|
23 |
+
'items': []
|
24 |
+
}
|
25 |
+
for item in extra_page.list_items():
|
26 |
+
# 解析metadata
|
27 |
+
output_name = None
|
28 |
+
try:
|
29 |
+
if 'metadata' in item and item['metadata']:
|
30 |
+
metadata = json.loads(item['metadata'])
|
31 |
+
if metadata and 'ss_output_name' in metadata:
|
32 |
+
output_name = metadata['ss_output_name']
|
33 |
+
except Exception as e:
|
34 |
+
pass
|
35 |
+
item['output_name'] = output_name
|
36 |
+
|
37 |
+
# 获取civitai.info
|
38 |
+
item['civitai_info'] = {}
|
39 |
+
try:
|
40 |
+
if 'filename' in item and item['filename']:
|
41 |
+
if extra_page.name == 'textual inversion':
|
42 |
+
base, ext = os.path.splitext(item['filename'])
|
43 |
+
info_file = base + '.civitai.info'
|
44 |
+
else:
|
45 |
+
info_file = item['filename'] + '.civitai.info'
|
46 |
+
if os.path.isfile(info_file):
|
47 |
+
with open(info_file, 'r') as f:
|
48 |
+
info = json.load(f)
|
49 |
+
info = {
|
50 |
+
'name': info.get('name', ''),
|
51 |
+
'model': info.get('model', {}),
|
52 |
+
}
|
53 |
+
item['civitai_info'] = info
|
54 |
+
except Exception as e:
|
55 |
+
pass
|
56 |
+
|
57 |
+
# 过滤掉不需要的字段
|
58 |
+
for filter in filters:
|
59 |
+
if filter in item:
|
60 |
+
del item[filter]
|
61 |
+
|
62 |
+
result_item['items'].append(item)
|
63 |
+
|
64 |
+
result.append(result_item)
|
65 |
+
except Exception as e:
|
66 |
+
pass
|
67 |
+
return result
|
scripts/physton_prompt/get_group_tags.py
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
4 |
+
|
5 |
+
def _get_tags_filename(name):
|
6 |
+
file = os.path.join(current_dir, '../../group_tags/', name + '.yaml')
|
7 |
+
return file
|
8 |
+
|
9 |
+
def get_group_tags(lang):
|
10 |
+
tags_file = _get_tags_filename('custom')
|
11 |
+
if not os.path.exists(tags_file):
|
12 |
+
tags_file = _get_tags_filename(lang)
|
13 |
+
if not os.path.exists(tags_file):
|
14 |
+
tags_file = _get_tags_filename('default')
|
15 |
+
if not os.path.exists(tags_file):
|
16 |
+
return ''
|
17 |
+
|
18 |
+
tags = ''
|
19 |
+
|
20 |
+
try:
|
21 |
+
prepend_file = _get_tags_filename('prepend')
|
22 |
+
with open(prepend_file, 'r', encoding='utf8') as f:
|
23 |
+
prepend = f.read()
|
24 |
+
tags += prepend + "\n\n"
|
25 |
+
except:
|
26 |
+
pass
|
27 |
+
|
28 |
+
try:
|
29 |
+
with open(tags_file, 'r', encoding='utf8') as f:
|
30 |
+
data = f.read()
|
31 |
+
tags += data + "\n\n"
|
32 |
+
except:
|
33 |
+
pass
|
34 |
+
|
35 |
+
try:
|
36 |
+
append_file = _get_tags_filename('append')
|
37 |
+
with open(append_file, 'r', encoding='utf8') as f:
|
38 |
+
append = f.read()
|
39 |
+
tags += append + "\n\n"
|
40 |
+
except:
|
41 |
+
pass
|
42 |
+
|
43 |
+
return tags
|
scripts/physton_prompt/get_i18n.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
|
4 |
+
i18n = {}
|
5 |
+
|
6 |
+
|
7 |
+
def get_i18n(reload=False):
|
8 |
+
global i18n
|
9 |
+
if reload or not i18n:
|
10 |
+
i18n = {}
|
11 |
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
12 |
+
config_file = os.path.join(current_dir, '../../i18n.json')
|
13 |
+
config_file = os.path.normpath(config_file)
|
14 |
+
with open(config_file, 'r', encoding='utf8') as f:
|
15 |
+
i18n = json.load(f)
|
16 |
+
return i18n
|
scripts/physton_prompt/get_lang.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.storage import Storage
|
2 |
+
|
3 |
+
storage = Storage()
|
4 |
+
from scripts.physton_prompt.get_i18n import get_i18n
|
5 |
+
|
6 |
+
|
7 |
+
def replace_vars(text, vars):
|
8 |
+
for key, value in vars.items():
|
9 |
+
text = text.replace("{" + key + "}", value)
|
10 |
+
return text
|
11 |
+
|
12 |
+
|
13 |
+
def get_lang(key, vars={}):
|
14 |
+
i18n = get_i18n()
|
15 |
+
code = storage.get('languageCode')
|
16 |
+
|
17 |
+
def find_lang(code):
|
18 |
+
for item in i18n['languages']:
|
19 |
+
if item['code'] == code:
|
20 |
+
return True
|
21 |
+
return False
|
22 |
+
|
23 |
+
if not find_lang(code):
|
24 |
+
code = i18n['default']
|
25 |
+
|
26 |
+
if not find_lang(code):
|
27 |
+
code = 'en_US'
|
28 |
+
|
29 |
+
def find_key(key, code):
|
30 |
+
for item in i18n['languages']:
|
31 |
+
if item['code'] == code:
|
32 |
+
if key in item['lang']:
|
33 |
+
if vars == {}:
|
34 |
+
return item['lang'][key]
|
35 |
+
else:
|
36 |
+
return replace_vars(item['lang'][key], vars)
|
37 |
+
return False
|
38 |
+
|
39 |
+
find = find_key(key, code)
|
40 |
+
if find:
|
41 |
+
return find
|
42 |
+
|
43 |
+
find = find_key(key, 'en_US')
|
44 |
+
if find:
|
45 |
+
return find
|
46 |
+
|
47 |
+
return replace_vars(key, vars)
|
scripts/physton_prompt/get_token_counter.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from modules import script_callbacks, extra_networks, prompt_parser
|
2 |
+
from modules.sd_hijack import model_hijack
|
3 |
+
from functools import partial, reduce
|
4 |
+
|
5 |
+
|
6 |
+
def get_token_counter(text, steps):
|
7 |
+
# copy from modules.ui.py
|
8 |
+
try:
|
9 |
+
text, _ = extra_networks.parse_prompt(text)
|
10 |
+
|
11 |
+
_, prompt_flat_list, _ = prompt_parser.get_multicond_prompt_list([text])
|
12 |
+
prompt_schedules = prompt_parser.get_learned_conditioning_prompt_schedules(prompt_flat_list, steps)
|
13 |
+
|
14 |
+
except Exception:
|
15 |
+
# a parsing error can happen here during typing, and we don't want to bother the user with
|
16 |
+
# messages related to it in console
|
17 |
+
prompt_schedules = [[[steps, text]]]
|
18 |
+
|
19 |
+
flat_prompts = reduce(lambda list1, list2: list1 + list2, prompt_schedules)
|
20 |
+
prompts = [prompt_text for step, prompt_text in flat_prompts]
|
21 |
+
token_count, max_length = max([model_hijack.get_prompt_lengths(prompt) for prompt in prompts],
|
22 |
+
key=lambda args: args[0])
|
23 |
+
return {"token_count": token_count, "max_length": max_length}
|
scripts/physton_prompt/get_translate_apis.py
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
import re
|
4 |
+
from scripts.physton_prompt.storage import Storage
|
5 |
+
st = Storage()
|
6 |
+
|
7 |
+
# from scripts.physton_prompt.storage import Storage
|
8 |
+
|
9 |
+
translate_apis = {}
|
10 |
+
|
11 |
+
|
12 |
+
# st = Storage()
|
13 |
+
def get_translate_apis(reload=False):
|
14 |
+
global translate_apis
|
15 |
+
global st
|
16 |
+
if reload or not translate_apis:
|
17 |
+
translate_apis = {}
|
18 |
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
19 |
+
config_file = os.path.join(current_dir, '../../translate_apis.json')
|
20 |
+
config_file = os.path.normpath(config_file)
|
21 |
+
with open(config_file, 'r', encoding='utf8') as f:
|
22 |
+
translate_apis = json.load(f)
|
23 |
+
|
24 |
+
# for group in translate_apis['apis']:
|
25 |
+
# for item in group['children']:
|
26 |
+
# if 'config' not in item:
|
27 |
+
# continue
|
28 |
+
# config_name = 'translate_api.' + item['key']
|
29 |
+
# config = st.get(config_name)
|
30 |
+
# if not config:
|
31 |
+
# config = {}
|
32 |
+
# for config_item in item['config']:
|
33 |
+
# if config_item['key'] in config:
|
34 |
+
# config_item['value'] = config[config_item['key']]
|
35 |
+
# else:
|
36 |
+
# if 'default' in config_item:
|
37 |
+
# config_item['value'] = config_item['default']
|
38 |
+
# else:
|
39 |
+
# config_item['value'] = ''
|
40 |
+
|
41 |
+
return translate_apis
|
42 |
+
|
43 |
+
|
44 |
+
def privacy_translate_api_config(data_key, data):
|
45 |
+
# 如果 data 为空或者不是 dict
|
46 |
+
if not data or not isinstance(data, dict):
|
47 |
+
return data
|
48 |
+
# 如果 data_key 是 translate_api. 开头
|
49 |
+
api = None
|
50 |
+
if data_key == 'chatgpt_key':
|
51 |
+
api = 'openai'
|
52 |
+
else:
|
53 |
+
start = 'translate_api.'
|
54 |
+
if not data_key.startswith(start):
|
55 |
+
return data
|
56 |
+
api = data_key[len(start):]
|
57 |
+
apis = get_translate_apis()
|
58 |
+
find = False
|
59 |
+
for group in apis['apis']:
|
60 |
+
for item in group['children']:
|
61 |
+
if item['key'] == api:
|
62 |
+
find = item
|
63 |
+
break
|
64 |
+
if not find:
|
65 |
+
return data
|
66 |
+
api_item = find
|
67 |
+
if 'config' not in api_item or not api_item['config']:
|
68 |
+
return data
|
69 |
+
|
70 |
+
for config in api_item['config']:
|
71 |
+
# 如果有 privacy 的属性并且为 True
|
72 |
+
if 'privacy' in config and config['privacy'] and config['type'] == 'input':
|
73 |
+
if config['key'] in data:
|
74 |
+
# 前面6个字符可见,后面的字符用 * 替换
|
75 |
+
value = data[config['key']]
|
76 |
+
if len(value) > 6:
|
77 |
+
value = value[:6] + '*' * (len(value) - 6)
|
78 |
+
data[config['key']] = value
|
79 |
+
|
80 |
+
return data
|
81 |
+
|
82 |
+
def unprotected_translate_api_config(data_key, data):
|
83 |
+
api = None
|
84 |
+
if data_key == 'chatgpt_key':
|
85 |
+
api = 'openai'
|
86 |
+
else:
|
87 |
+
start = 'translate_api.'
|
88 |
+
if not data_key.startswith(start):
|
89 |
+
return data
|
90 |
+
api = data_key[len(start):]
|
91 |
+
|
92 |
+
apis = get_translate_apis()
|
93 |
+
find = False
|
94 |
+
for group in apis['apis']:
|
95 |
+
for item in group['children']:
|
96 |
+
if item['key'] == api:
|
97 |
+
find = item
|
98 |
+
break
|
99 |
+
if not find:
|
100 |
+
return data
|
101 |
+
api_item = find
|
102 |
+
if 'config' not in api_item or not api_item['config']:
|
103 |
+
return data
|
104 |
+
|
105 |
+
storage_data = st.get(data_key)
|
106 |
+
|
107 |
+
for config in api_item['config']:
|
108 |
+
# 如果有 privacy 的属性并且为 True
|
109 |
+
if 'privacy' in config and config['privacy'] and config['type'] == 'input':
|
110 |
+
if storage_data and config['key'] in storage_data:
|
111 |
+
if config['key'] in data:
|
112 |
+
value = data[config['key']]
|
113 |
+
# 如果包含 * 号,并且前面6个字符等于 storage_data 的前面6个字符
|
114 |
+
if '*' in value and value[:6] == storage_data[config['key']][:6]:
|
115 |
+
data[config['key']] = storage_data[config['key']]
|
116 |
+
|
117 |
+
# 多个 * 替换成一个 *
|
118 |
+
# value = re.sub(r'\*+', '*', value)
|
119 |
+
# if value == '*' and storage_data and config['key'] in storage_data:
|
120 |
+
# value = storage_data[config['key']]
|
121 |
+
# data[config['key']] = value
|
122 |
+
|
123 |
+
return data
|
scripts/physton_prompt/get_version.py
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import re
|
3 |
+
import requests
|
4 |
+
import subprocess
|
5 |
+
import hashlib
|
6 |
+
|
7 |
+
|
8 |
+
def get_git_commit_version():
|
9 |
+
extension_dir = os.path.dirname(os.path.abspath(__file__)) + '/../../'
|
10 |
+
extension_dir = os.path.normpath(extension_dir)
|
11 |
+
git_path = os.path.join(extension_dir, '.git')
|
12 |
+
if os.path.exists(git_path):
|
13 |
+
try:
|
14 |
+
git = os.environ.get('GIT', "git")
|
15 |
+
if not git:
|
16 |
+
git = "git"
|
17 |
+
cmd = [git, 'rev-parse', 'HEAD']
|
18 |
+
commit_version = subprocess.check_output(cmd, cwd=extension_dir).decode('utf-8').strip()
|
19 |
+
if re.match(r'^[0-9a-f]{40}$', commit_version):
|
20 |
+
return commit_version
|
21 |
+
except Exception as e:
|
22 |
+
pass
|
23 |
+
|
24 |
+
try:
|
25 |
+
ref_path = os.path.join(git_path, 'refs', 'heads', 'main')
|
26 |
+
with open(ref_path, 'r') as f:
|
27 |
+
commit_version = f.read().strip()
|
28 |
+
if re.match(r'^[0-9a-f]{40}$', commit_version):
|
29 |
+
return commit_version
|
30 |
+
except Exception as e:
|
31 |
+
pass
|
32 |
+
|
33 |
+
return ''
|
34 |
+
|
35 |
+
|
36 |
+
def _handle_versions(response, filter_update_readme=False):
|
37 |
+
try:
|
38 |
+
if response.status_code != 200:
|
39 |
+
return []
|
40 |
+
result = response.json()
|
41 |
+
if not result:
|
42 |
+
return []
|
43 |
+
versions = []
|
44 |
+
for item in result:
|
45 |
+
message = item['commit']['message']
|
46 |
+
is_update_readme = False
|
47 |
+
if message.lower().strip() == 'update readme.md':
|
48 |
+
if filter_update_readme:
|
49 |
+
continue
|
50 |
+
is_update_readme = True
|
51 |
+
versions.append({
|
52 |
+
'version': item['sha'],
|
53 |
+
'message': message,
|
54 |
+
'date': item['commit']['committer']['date'],
|
55 |
+
'is_update_readme': is_update_readme
|
56 |
+
})
|
57 |
+
return versions
|
58 |
+
except Exception as e:
|
59 |
+
return []
|
60 |
+
|
61 |
+
|
62 |
+
def get_git_remote_versions(page=1, per_page=100, filter_update_readme=False):
|
63 |
+
api_urls = [
|
64 |
+
'https://api.github.com/repos/physton/sd-webui-prompt-all-in-one/commits',
|
65 |
+
'https://gitee.com/api/v5/repos/physton/sd-webui-prompt-all-in-one/commits'
|
66 |
+
]
|
67 |
+
|
68 |
+
for api_url in api_urls:
|
69 |
+
try:
|
70 |
+
api_url += f'?page={page}&per_page={per_page}'
|
71 |
+
key = hashlib.md5(api_url.encode('utf-8')).hexdigest()
|
72 |
+
response = requests.get(api_url)
|
73 |
+
versions = _handle_versions(response, filter_update_readme)
|
74 |
+
return versions
|
75 |
+
except Exception as e:
|
76 |
+
pass
|
77 |
+
|
78 |
+
return []
|
79 |
+
|
80 |
+
|
81 |
+
def get_latest_version():
|
82 |
+
current_version = get_git_commit_version()
|
83 |
+
# if not current_version:
|
84 |
+
# return current_version
|
85 |
+
versions = get_git_remote_versions(1, 10, False)
|
86 |
+
if len(versions) < 1:
|
87 |
+
return current_version
|
88 |
+
return versions[0]['version']
|
scripts/physton_prompt/history.py
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.storage import Storage
|
2 |
+
import uuid
|
3 |
+
import time
|
4 |
+
|
5 |
+
|
6 |
+
class History:
|
7 |
+
histories = {
|
8 |
+
'txt2img': [],
|
9 |
+
'txt2img_neg': [],
|
10 |
+
'img2img': [],
|
11 |
+
'img2img_neg': [],
|
12 |
+
}
|
13 |
+
favorites = {
|
14 |
+
'txt2img': [],
|
15 |
+
'txt2img_neg': [],
|
16 |
+
'img2img': [],
|
17 |
+
'img2img_neg': [],
|
18 |
+
}
|
19 |
+
max = 100
|
20 |
+
storage = Storage()
|
21 |
+
|
22 |
+
def __init__(self):
|
23 |
+
for type in self.histories:
|
24 |
+
self.histories[type] = self.storage.get('history.' + type)
|
25 |
+
if self.histories[type] is None:
|
26 |
+
self.histories[type] = []
|
27 |
+
self.__save_histories(type)
|
28 |
+
|
29 |
+
for type in self.favorites:
|
30 |
+
self.favorites[type] = self.storage.get('favorite.' + type)
|
31 |
+
if self.favorites[type] is None:
|
32 |
+
self.favorites[type] = []
|
33 |
+
self.__save_favorites(type)
|
34 |
+
|
35 |
+
def __save_histories(self, type):
|
36 |
+
self.storage.set('history.' + type, self.histories[type])
|
37 |
+
|
38 |
+
def __save_favorites(self, type):
|
39 |
+
self.storage.set('favorite.' + type, self.favorites[type])
|
40 |
+
|
41 |
+
def get_histories(self, type):
|
42 |
+
histories = self.histories[type]
|
43 |
+
for history in histories:
|
44 |
+
history['is_favorite'] = self.is_favorite(type, history['id'])
|
45 |
+
return histories
|
46 |
+
|
47 |
+
def is_favorite(self, type, id):
|
48 |
+
for favorite in self.favorites[type]:
|
49 |
+
if favorite['id'] == id:
|
50 |
+
return True
|
51 |
+
return False
|
52 |
+
|
53 |
+
def get_favorites(self, type):
|
54 |
+
return self.favorites[type]
|
55 |
+
|
56 |
+
def push_history(self, type, tags, prompt, name=''):
|
57 |
+
if len(self.histories[type]) >= self.max:
|
58 |
+
self.histories[type].pop(0)
|
59 |
+
item = {
|
60 |
+
'id': str(uuid.uuid1()),
|
61 |
+
'time': int(time.time()),
|
62 |
+
'name': name,
|
63 |
+
'tags': tags,
|
64 |
+
'prompt': prompt,
|
65 |
+
}
|
66 |
+
self.histories[type].append(item)
|
67 |
+
self.__save_histories(type)
|
68 |
+
return item
|
69 |
+
|
70 |
+
def push_favorite(self, type, tags, prompt, name=''):
|
71 |
+
item = {
|
72 |
+
'id': str(uuid.uuid1()),
|
73 |
+
'time': int(time.time()),
|
74 |
+
'name': name,
|
75 |
+
'tags': tags,
|
76 |
+
'prompt': prompt,
|
77 |
+
}
|
78 |
+
self.favorites[type].append(item)
|
79 |
+
self.__save_favorites(type)
|
80 |
+
return item
|
81 |
+
|
82 |
+
def get_latest_history(self, type):
|
83 |
+
if len(self.histories[type]) > 0:
|
84 |
+
return self.histories[type][-1]
|
85 |
+
return None
|
86 |
+
|
87 |
+
def set_history(self, type, id, tags, prompt, name):
|
88 |
+
for history in self.histories[type]:
|
89 |
+
if history['id'] == id:
|
90 |
+
history['tags'] = tags
|
91 |
+
history['prompt'] = prompt
|
92 |
+
history['name'] = name
|
93 |
+
self.__save_histories(type)
|
94 |
+
if self.is_favorite(type, id):
|
95 |
+
self.set_favorite(type, id, tags, prompt, name)
|
96 |
+
return True
|
97 |
+
return False
|
98 |
+
|
99 |
+
def set_favorite(self, type, id, tags, prompt, name):
|
100 |
+
for favorite in self.favorites[type]:
|
101 |
+
if favorite['id'] == id:
|
102 |
+
favorite['tags'] = tags
|
103 |
+
favorite['prompt'] = prompt
|
104 |
+
favorite['name'] = name
|
105 |
+
self.__save_favorites(type)
|
106 |
+
return True
|
107 |
+
return False
|
108 |
+
|
109 |
+
def set_history_name(self, type, id, name):
|
110 |
+
for history in self.histories[type]:
|
111 |
+
if history['id'] == id:
|
112 |
+
history['name'] = name
|
113 |
+
self.__save_histories(type)
|
114 |
+
for favorite in self.favorites[type]:
|
115 |
+
if favorite['id'] == id:
|
116 |
+
favorite['name'] = name
|
117 |
+
self.__save_favorites(type)
|
118 |
+
return True
|
119 |
+
return False
|
120 |
+
|
121 |
+
def set_favorite_name(self, type, id, name):
|
122 |
+
for favorite in self.favorites[type]:
|
123 |
+
if favorite['id'] == id:
|
124 |
+
favorite['name'] = name
|
125 |
+
self.__save_favorites(type)
|
126 |
+
for history in self.histories[type]:
|
127 |
+
if history['id'] == id:
|
128 |
+
history['name'] = name
|
129 |
+
self.__save_histories(type)
|
130 |
+
return True
|
131 |
+
return False
|
132 |
+
|
133 |
+
def dofavorite(self, type, id):
|
134 |
+
if self.is_favorite(type, id):
|
135 |
+
return False
|
136 |
+
for history in self.histories[type]:
|
137 |
+
if history['id'] == id:
|
138 |
+
self.favorites[type].append(history)
|
139 |
+
self.__save_favorites(type)
|
140 |
+
return True
|
141 |
+
return False
|
142 |
+
|
143 |
+
def unfavorite(self, type, id):
|
144 |
+
if not self.is_favorite(type, id):
|
145 |
+
return False
|
146 |
+
for favorite in self.favorites[type]:
|
147 |
+
if favorite['id'] == id:
|
148 |
+
self.favorites[type].remove(favorite)
|
149 |
+
self.__save_favorites(type)
|
150 |
+
return True
|
151 |
+
return False
|
152 |
+
|
153 |
+
def remove_history(self, type, id):
|
154 |
+
for history in self.histories[type]:
|
155 |
+
if history['id'] == id:
|
156 |
+
self.histories[type].remove(history)
|
157 |
+
self.__save_histories(type)
|
158 |
+
return True
|
159 |
+
return False
|
160 |
+
|
161 |
+
def remove_histories(self, type):
|
162 |
+
self.histories[type] = []
|
163 |
+
self.__save_histories(type)
|
164 |
+
return True
|
scripts/physton_prompt/mbart50.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import time
|
3 |
+
from scripts.physton_prompt.get_lang import get_lang
|
4 |
+
|
5 |
+
model = None
|
6 |
+
tokenizer = None
|
7 |
+
model_name = "facebook/mbart-large-50-many-to-many-mmt"
|
8 |
+
cache_dir = os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + '/../../models')
|
9 |
+
loading = False
|
10 |
+
|
11 |
+
def initialize(reload=False):
|
12 |
+
global model, tokenizer, model_name, cache_dir, loading
|
13 |
+
if loading:
|
14 |
+
while not loading:
|
15 |
+
time.sleep(0.1)
|
16 |
+
pass
|
17 |
+
if model is None or tokenizer is None:
|
18 |
+
raise Exception('error')
|
19 |
+
# raise Exception(get_lang('model_is_loading'))
|
20 |
+
return
|
21 |
+
if not reload and model is not None:
|
22 |
+
return
|
23 |
+
loading = True
|
24 |
+
model = None
|
25 |
+
tokenizer = None
|
26 |
+
|
27 |
+
model_path = os.path.join(cache_dir, "mbart-large-50-many-to-many-mmt")
|
28 |
+
model_file = os.path.join(model_path, "pytorch_model.bin")
|
29 |
+
if os.path.exists(model_path) and os.path.exists(model_file):
|
30 |
+
model_name = model_path
|
31 |
+
|
32 |
+
try:
|
33 |
+
from transformers import MBart50TokenizerFast, MBartForConditionalGeneration
|
34 |
+
print(f'[sd-webui-prompt-all-in-one] Loading model {model_name} from {cache_dir}...')
|
35 |
+
model = MBartForConditionalGeneration.from_pretrained(model_name, cache_dir=cache_dir)
|
36 |
+
tokenizer = MBart50TokenizerFast.from_pretrained(model_name, cache_dir=cache_dir)
|
37 |
+
print(f'[sd-webui-prompt-all-in-one] Model {model_name} loaded.')
|
38 |
+
loading = False
|
39 |
+
except Exception as e:
|
40 |
+
loading = False
|
41 |
+
raise e
|
42 |
+
|
43 |
+
def translate(text, src_lang, target_lang):
|
44 |
+
global model, tokenizer
|
45 |
+
|
46 |
+
if not text:
|
47 |
+
if isinstance(text, list):
|
48 |
+
return []
|
49 |
+
else:
|
50 |
+
return ''
|
51 |
+
|
52 |
+
if model is None:
|
53 |
+
raise Exception(get_lang('model_not_initialized'))
|
54 |
+
|
55 |
+
if tokenizer is None:
|
56 |
+
raise Exception(get_lang('model_not_initialized'))
|
57 |
+
|
58 |
+
if src_lang == target_lang:
|
59 |
+
return text
|
60 |
+
|
61 |
+
tokenizer.src_lang = src_lang
|
62 |
+
encoded_input = tokenizer(text, return_tensors="pt", padding=True)
|
63 |
+
generated_tokens = model.generate(
|
64 |
+
**encoded_input, forced_bos_token_id=tokenizer.lang_code_to_id[target_lang],
|
65 |
+
max_new_tokens=500
|
66 |
+
)
|
67 |
+
return tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)
|
scripts/physton_prompt/packages.py
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import launch
|
2 |
+
from scripts.physton_prompt.get_lang import get_lang
|
3 |
+
|
4 |
+
packages = {
|
5 |
+
"chardet": "chardet",
|
6 |
+
"fastapi": "fastapi",
|
7 |
+
"execjs": "PyExecJS",
|
8 |
+
"lxml": "lxml",
|
9 |
+
"tqdm": "tqdm",
|
10 |
+
"pathos": "pathos",
|
11 |
+
"cryptography": "cryptography",
|
12 |
+
|
13 |
+
# The following packages are required for translation service. If you do not need translation service, you can remove them.
|
14 |
+
# 以下是翻译所需的包,如果不需要翻译服务,可以删除掉它们。
|
15 |
+
"openai": "openai",
|
16 |
+
"boto3": "boto3",
|
17 |
+
"aliyunsdkcore": "aliyun-python-sdk-core",
|
18 |
+
"aliyunsdkalimt": "aliyun-python-sdk-alimt",
|
19 |
+
}
|
20 |
+
|
21 |
+
|
22 |
+
def get_packages_state():
|
23 |
+
states = []
|
24 |
+
for package_name in packages:
|
25 |
+
package = packages[package_name]
|
26 |
+
item = {
|
27 |
+
'name': package_name,
|
28 |
+
'package': package,
|
29 |
+
'state': False
|
30 |
+
}
|
31 |
+
if launch.is_installed(package) or launch.is_installed(package_name):
|
32 |
+
item['state'] = True
|
33 |
+
|
34 |
+
states.append(item)
|
35 |
+
|
36 |
+
return states
|
37 |
+
|
38 |
+
|
39 |
+
def install_package(name, package):
|
40 |
+
result = {'state': False, 'message': ''}
|
41 |
+
try:
|
42 |
+
launch.run_pip(f"install {package}", f"sd-webui-prompt-all-in-one: {name}")
|
43 |
+
result['state'] = True
|
44 |
+
result['message'] = get_lang('install_success', {'0': package})
|
45 |
+
except Exception as e:
|
46 |
+
print(e)
|
47 |
+
print(f'Warning: Failed to install {package}, some preprocessors may not work.')
|
48 |
+
result['message'] = get_lang('install_failed', {'0': package}) + '\n' + str(e)
|
49 |
+
return result
|
scripts/physton_prompt/storage.py
ADDED
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from pathlib import Path
|
3 |
+
import json
|
4 |
+
import time
|
5 |
+
|
6 |
+
|
7 |
+
class Storage:
|
8 |
+
storage_path = ''
|
9 |
+
|
10 |
+
def __init__(self):
|
11 |
+
pass
|
12 |
+
|
13 |
+
def __get_storage_path(self):
|
14 |
+
self.storage_path = os.path.dirname(os.path.abspath(__file__)) + '/../../storage'
|
15 |
+
self.storage_path = os.path.normpath(self.storage_path)
|
16 |
+
if not os.path.exists(self.storage_path):
|
17 |
+
os.makedirs(self.storage_path)
|
18 |
+
|
19 |
+
# old_storage_path = os.path.join(Path().absolute(), 'physton-prompt')
|
20 |
+
# if os.path.exists(old_storage_path):
|
21 |
+
# # 复制就的存储文件到新的存储文件夹
|
22 |
+
# for file in os.listdir(old_storage_path):
|
23 |
+
# old_file_path = os.path.join(old_storage_path, file)
|
24 |
+
# new_file_path = os.path.join(self.storage_path, file)
|
25 |
+
# if not os.path.exists(new_file_path):
|
26 |
+
# os.rename(old_file_path, new_file_path)
|
27 |
+
# # 删除旧的存储文件夹
|
28 |
+
# os.rmdir(old_storage_path)
|
29 |
+
|
30 |
+
return self.storage_path
|
31 |
+
|
32 |
+
def __get_data_filename(self, key):
|
33 |
+
return self.__get_storage_path() + '/' + key + '.json'
|
34 |
+
|
35 |
+
def __get_key_lock_filename(self, key):
|
36 |
+
return self.__get_storage_path() + '/' + key + '.lock'
|
37 |
+
|
38 |
+
def __lock(self, key):
|
39 |
+
file_path = self.__get_key_lock_filename(key)
|
40 |
+
with open(file_path, 'w') as f:
|
41 |
+
f.write('1')
|
42 |
+
|
43 |
+
def __unlock(self, key):
|
44 |
+
file_path = self.__get_key_lock_filename(key)
|
45 |
+
if os.path.exists(file_path):
|
46 |
+
os.remove(file_path)
|
47 |
+
|
48 |
+
def __is_locked(self, key):
|
49 |
+
file_path = self.__get_key_lock_filename(key)
|
50 |
+
return os.path.exists(file_path)
|
51 |
+
|
52 |
+
def __get(self, key):
|
53 |
+
filename = self.__get_data_filename(key)
|
54 |
+
if not os.path.exists(filename):
|
55 |
+
return None
|
56 |
+
if os.path.getsize(filename) == 0:
|
57 |
+
return None
|
58 |
+
try:
|
59 |
+
import launch
|
60 |
+
if not launch.is_installed("chardet"):
|
61 |
+
with open(filename, 'r') as f:
|
62 |
+
data = json.load(f)
|
63 |
+
else:
|
64 |
+
import chardet
|
65 |
+
with open(filename, 'rb') as f:
|
66 |
+
data = f.read()
|
67 |
+
encoding = chardet.detect(data).get('encoding')
|
68 |
+
data = json.loads(data.decode(encoding))
|
69 |
+
except Exception as e:
|
70 |
+
try:
|
71 |
+
with open(filename, 'r') as f:
|
72 |
+
data = json.load(f)
|
73 |
+
except Exception as e:
|
74 |
+
print(e)
|
75 |
+
return None
|
76 |
+
return data
|
77 |
+
|
78 |
+
def __set(self, key, data):
|
79 |
+
file_path = self.__get_data_filename(key)
|
80 |
+
with open(file_path, 'w') as f:
|
81 |
+
json.dump(data, f, indent=4, ensure_ascii=True)
|
82 |
+
|
83 |
+
def set(self, key, data):
|
84 |
+
while self.__is_locked(key):
|
85 |
+
time.sleep(0.01)
|
86 |
+
self.__lock(key)
|
87 |
+
try:
|
88 |
+
self.__set(key, data)
|
89 |
+
self.__unlock(key)
|
90 |
+
except Exception as e:
|
91 |
+
self.__unlock(key)
|
92 |
+
raise e
|
93 |
+
|
94 |
+
def get(self, key):
|
95 |
+
return self.__get(key)
|
96 |
+
|
97 |
+
def delete(self, key):
|
98 |
+
file_path = self.__get_data_filename(key)
|
99 |
+
if os.path.exists(file_path):
|
100 |
+
os.remove(file_path)
|
101 |
+
|
102 |
+
def __get_list(self, key):
|
103 |
+
data = self.get(key)
|
104 |
+
if not data:
|
105 |
+
data = []
|
106 |
+
return data
|
107 |
+
|
108 |
+
# 向列表中添加元素
|
109 |
+
def list_push(self, key, item):
|
110 |
+
while self.__is_locked(key):
|
111 |
+
time.sleep(0.01)
|
112 |
+
self.__lock(key)
|
113 |
+
try:
|
114 |
+
data = self.__get_list(key)
|
115 |
+
data.append(item)
|
116 |
+
self.__set(key, data)
|
117 |
+
self.__unlock(key)
|
118 |
+
except Exception as e:
|
119 |
+
self.__unlock(key)
|
120 |
+
raise e
|
121 |
+
|
122 |
+
# 从列表中删除和返回最后一个元素
|
123 |
+
def list_pop(self, key):
|
124 |
+
while self.__is_locked(key):
|
125 |
+
time.sleep(0.01)
|
126 |
+
self.__lock(key)
|
127 |
+
try:
|
128 |
+
data = self.__get_list(key)
|
129 |
+
item = data.pop()
|
130 |
+
self.__set(key, data)
|
131 |
+
self.__unlock(key)
|
132 |
+
return item
|
133 |
+
except Exception as e:
|
134 |
+
self.__unlock(key)
|
135 |
+
raise e
|
136 |
+
|
137 |
+
# 从列表中删除和返回第一个元素
|
138 |
+
def list_shift(self, key):
|
139 |
+
while self.__is_locked(key):
|
140 |
+
time.sleep(0.01)
|
141 |
+
self.__lock(key)
|
142 |
+
try:
|
143 |
+
data = self.__get_list(key)
|
144 |
+
item = data.pop(0)
|
145 |
+
self.__set(key, data)
|
146 |
+
self.__unlock(key)
|
147 |
+
return item
|
148 |
+
except Exception as e:
|
149 |
+
self.__unlock(key)
|
150 |
+
raise e
|
151 |
+
|
152 |
+
# 从列表中删除指定元素
|
153 |
+
def list_remove(self, key, index):
|
154 |
+
while self.__is_locked(key):
|
155 |
+
time.sleep(0.01)
|
156 |
+
self.__lock(key)
|
157 |
+
data = self.__get_list(key)
|
158 |
+
data.pop(index)
|
159 |
+
self.__set(key, data)
|
160 |
+
self.__unlock(key)
|
161 |
+
|
162 |
+
# 获取列表中指定位置的元素
|
163 |
+
def list_get(self, key, index):
|
164 |
+
data = self.__get_list(key)
|
165 |
+
return data[index]
|
166 |
+
|
167 |
+
# 清空列表中的所有元素
|
168 |
+
def list_clear(self, key):
|
169 |
+
while self.__is_locked(key):
|
170 |
+
time.sleep(0.01)
|
171 |
+
self.__lock(key)
|
172 |
+
try:
|
173 |
+
self.__set(key, [])
|
174 |
+
self.__unlock(key)
|
175 |
+
except Exception as e:
|
176 |
+
self.__unlock(key)
|
177 |
+
raise e
|
scripts/physton_prompt/styles.py
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from scripts.physton_prompt.storage import Storage
|
3 |
+
|
4 |
+
storage = Storage()
|
5 |
+
|
6 |
+
styles_path = os.path.dirname(os.path.abspath(__file__)) + '/../../styles'
|
7 |
+
styles_path = os.path.normpath(styles_path)
|
8 |
+
|
9 |
+
|
10 |
+
def get_style_full_path(file):
|
11 |
+
global styles_path
|
12 |
+
return os.path.join(styles_path, file)
|
13 |
+
|
14 |
+
|
15 |
+
def get_extension_css_list():
|
16 |
+
global styles_path
|
17 |
+
extension_path = os.path.join(styles_path, 'extensions')
|
18 |
+
if not os.path.exists(extension_path):
|
19 |
+
return []
|
20 |
+
css_list = []
|
21 |
+
# 扫描下面的每个文件夹
|
22 |
+
for dir in os.listdir(extension_path):
|
23 |
+
dir_path = os.path.join(extension_path, dir)
|
24 |
+
if not os.path.isdir(dir_path):
|
25 |
+
continue
|
26 |
+
|
27 |
+
# 是否有 manifest.json 文件
|
28 |
+
manifest_path = os.path.join(dir_path, 'manifest.json')
|
29 |
+
if not os.path.exists(manifest_path):
|
30 |
+
continue
|
31 |
+
|
32 |
+
# 是否有 style.min.css 文件
|
33 |
+
style_path = os.path.join(dir_path, 'style.min.css')
|
34 |
+
if not os.path.exists(style_path):
|
35 |
+
continue
|
36 |
+
|
37 |
+
manifest = None
|
38 |
+
try:
|
39 |
+
with open(manifest_path, 'r', encoding='utf8', errors='ignore') as f:
|
40 |
+
manifest = f.read()
|
41 |
+
except Exception as e:
|
42 |
+
print(f'读取 {manifest_path} 失败:{e}')
|
43 |
+
pass
|
44 |
+
if not manifest:
|
45 |
+
continue
|
46 |
+
|
47 |
+
css_item = {
|
48 |
+
'dir': dir,
|
49 |
+
'dataName': 'extensionSelect.' + dir,
|
50 |
+
'selected': False,
|
51 |
+
'manifest': manifest,
|
52 |
+
'style': f'extensions/{dir}/style.min.css',
|
53 |
+
}
|
54 |
+
css_item['selected'] = storage.get(css_item['dataName'])
|
55 |
+
css_list.append(css_item)
|
56 |
+
|
57 |
+
return css_list
|
scripts/physton_prompt/translate.py
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import hashlib
|
3 |
+
from scripts.physton_prompt.get_lang import get_lang
|
4 |
+
from scripts.physton_prompt.get_translate_apis import get_translate_apis, unprotected_translate_api_config
|
5 |
+
from scripts.physton_prompt.translator.alibaba_translator import AlibabaTranslator
|
6 |
+
from scripts.physton_prompt.translator.amazon_translator import AmazonTranslator
|
7 |
+
from scripts.physton_prompt.translator.baidu_translator import BaiduTranslator
|
8 |
+
from scripts.physton_prompt.translator.deepl_translator import DeeplTranslator
|
9 |
+
from scripts.physton_prompt.translator.google_tanslator import GoogleTranslator
|
10 |
+
from scripts.physton_prompt.translator.microsoft_translator import MicrosoftTranslator
|
11 |
+
from scripts.physton_prompt.translator.openai_translator import OpenaiTranslator
|
12 |
+
from scripts.physton_prompt.translator.tencent_translator import TencentTranslator
|
13 |
+
from scripts.physton_prompt.translator.translators_translator import TranslatorsTranslator
|
14 |
+
from scripts.physton_prompt.translator.yandex_translator import YandexTranslator
|
15 |
+
from scripts.physton_prompt.translator.youdao_translator import YoudaoTranslator
|
16 |
+
from scripts.physton_prompt.translator.mymemory_translator import MyMemoryTranslator
|
17 |
+
from scripts.physton_prompt.translator.niutrans_translator import NiutransTranslator
|
18 |
+
from scripts.physton_prompt.translator.caiyun_translator import CaiyunTranslator
|
19 |
+
from scripts.physton_prompt.translator.volcengine_translator import VolcengineTranslator
|
20 |
+
from scripts.physton_prompt.translator.iflytekV1_translator import IflytekV1Translator
|
21 |
+
from scripts.physton_prompt.translator.iflytekV2_translator import IflytekV2Translator
|
22 |
+
from scripts.physton_prompt.translator.mbart50_translator import MBart50Translator
|
23 |
+
|
24 |
+
caches = {}
|
25 |
+
|
26 |
+
|
27 |
+
def translate(text, from_lang, to_lang, api, api_config=None):
|
28 |
+
if api_config is None:
|
29 |
+
api_config = {}
|
30 |
+
global caches
|
31 |
+
|
32 |
+
def _translate_result(success, message, translated_text):
|
33 |
+
return {
|
34 |
+
"success": success,
|
35 |
+
"message": message,
|
36 |
+
"text": text,
|
37 |
+
"translated_text": translated_text,
|
38 |
+
"from_lang": from_lang,
|
39 |
+
"to_lang": to_lang,
|
40 |
+
"api": api
|
41 |
+
}
|
42 |
+
|
43 |
+
def _cache_name(text):
|
44 |
+
cache_name = f'{api}.{from_lang}.{to_lang}.{text}.' + json.dumps(api_config)
|
45 |
+
cache_name = hashlib.md5(cache_name.encode('utf-8')).hexdigest()
|
46 |
+
return cache_name
|
47 |
+
|
48 |
+
apis = get_translate_apis()
|
49 |
+
find = False
|
50 |
+
for group in apis['apis']:
|
51 |
+
for item in group['children']:
|
52 |
+
if item['key'] == api:
|
53 |
+
find = item
|
54 |
+
break
|
55 |
+
if not find:
|
56 |
+
return _translate_result(False, get_lang('translate_api_not_found'), '')
|
57 |
+
|
58 |
+
try:
|
59 |
+
texts = []
|
60 |
+
if isinstance(text, list):
|
61 |
+
if len(text) < 1:
|
62 |
+
return _translate_result(False, get_lang('translate_text_is_empty'), '')
|
63 |
+
for item in text:
|
64 |
+
texts.append(None)
|
65 |
+
for index in range(len(text)):
|
66 |
+
item = text[index]
|
67 |
+
item = item.strip()
|
68 |
+
if item == '':
|
69 |
+
texts[index] = ''
|
70 |
+
continue
|
71 |
+
cache_name = _cache_name(item)
|
72 |
+
if cache_name in caches:
|
73 |
+
texts[index] = caches[cache_name]
|
74 |
+
else:
|
75 |
+
texts[index] = None
|
76 |
+
else:
|
77 |
+
text = text.strip()
|
78 |
+
if text == '':
|
79 |
+
return _translate_result(False, get_lang('translate_text_is_empty'), '')
|
80 |
+
cache_name = _cache_name(text)
|
81 |
+
if cache_name in caches:
|
82 |
+
return _translate_result(True, '', caches[cache_name])
|
83 |
+
|
84 |
+
if api == 'google':
|
85 |
+
translator = GoogleTranslator()
|
86 |
+
elif api == 'microsoft':
|
87 |
+
translator = MicrosoftTranslator()
|
88 |
+
elif api == 'openai':
|
89 |
+
translator = OpenaiTranslator()
|
90 |
+
elif api == 'amazon':
|
91 |
+
translator = AmazonTranslator()
|
92 |
+
elif api == 'deepl':
|
93 |
+
translator = DeeplTranslator()
|
94 |
+
elif api == 'baidu':
|
95 |
+
translator = BaiduTranslator()
|
96 |
+
elif api == 'alibaba':
|
97 |
+
translator = AlibabaTranslator()
|
98 |
+
elif api == 'yandex':
|
99 |
+
translator = YandexTranslator()
|
100 |
+
elif api == 'youdao':
|
101 |
+
translator = YoudaoTranslator()
|
102 |
+
elif api == 'tencent':
|
103 |
+
translator = TencentTranslator()
|
104 |
+
elif api == 'myMemory_free' or api == 'myMemory':
|
105 |
+
translator = MyMemoryTranslator()
|
106 |
+
elif api == 'niutrans':
|
107 |
+
translator = NiutransTranslator()
|
108 |
+
elif api == 'caiyun':
|
109 |
+
translator = CaiyunTranslator()
|
110 |
+
elif api == 'volcengine':
|
111 |
+
translator = VolcengineTranslator()
|
112 |
+
elif api == 'iflytekV1':
|
113 |
+
translator = IflytekV1Translator()
|
114 |
+
elif api == 'iflytekV2':
|
115 |
+
translator = IflytekV2Translator()
|
116 |
+
elif api == 'mbart50':
|
117 |
+
translator = MBart50Translator()
|
118 |
+
elif 'type' in find and find['type'] == 'translators':
|
119 |
+
translator = TranslatorsTranslator(api)
|
120 |
+
translator.set_translator(find['translator'])
|
121 |
+
else:
|
122 |
+
return _translate_result(False, get_lang('translate_api_not_support'), '')
|
123 |
+
|
124 |
+
translator.set_from_lang(from_lang)
|
125 |
+
translator.set_to_lang(to_lang)
|
126 |
+
translator.set_api_config(unprotected_translate_api_config('translate_api.' + api, api_config))
|
127 |
+
|
128 |
+
if isinstance(text, list):
|
129 |
+
translate_texts = []
|
130 |
+
translate_indexes = []
|
131 |
+
for index in range(len(texts)):
|
132 |
+
item = texts[index]
|
133 |
+
if item is None:
|
134 |
+
translate_indexes.append(index)
|
135 |
+
translate_texts.append(text[index])
|
136 |
+
if len(translate_texts) < 1:
|
137 |
+
return _translate_result(True, '', texts)
|
138 |
+
result = translator.translate_batch(translate_texts)
|
139 |
+
for index in range(len(result)):
|
140 |
+
item = result[index]
|
141 |
+
texts[translate_indexes[index]] = item
|
142 |
+
caches[_cache_name(translate_texts[index])] = item
|
143 |
+
return _translate_result(True, '', texts)
|
144 |
+
else:
|
145 |
+
translated_text = translator.translate(text).strip()
|
146 |
+
caches[_cache_name(text)] = translated_text
|
147 |
+
return _translate_result(True, '', translated_text)
|
148 |
+
except Exception as e:
|
149 |
+
# print(e)
|
150 |
+
return _translate_result(False, str(e), '')
|
scripts/physton_prompt/translator/alibaba_translator.py
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import json
|
3 |
+
from math import ceil
|
4 |
+
from scripts.physton_prompt.get_lang import get_lang
|
5 |
+
|
6 |
+
|
7 |
+
class AlibabaTranslator(BaseTranslator):
|
8 |
+
def __init__(self):
|
9 |
+
super().__init__('alibaba')
|
10 |
+
|
11 |
+
def _get_config(self):
|
12 |
+
access_key_id = self.api_config.get('access_key_id', '')
|
13 |
+
access_key_secret = self.api_config.get('access_key_secret', '')
|
14 |
+
region = self.api_config.get('region', 'cn-shanghai')
|
15 |
+
if not access_key_id:
|
16 |
+
raise Exception(get_lang('is_required', {'0': 'Access Key ID'}))
|
17 |
+
if not access_key_secret:
|
18 |
+
raise Exception(get_lang('is_required', {'0': 'Access Key Secret'}))
|
19 |
+
if not region:
|
20 |
+
raise Exception(get_lang('is_required', {'0': 'Region ID'}))
|
21 |
+
return access_key_id, access_key_secret, region
|
22 |
+
|
23 |
+
def translate(self, text):
|
24 |
+
if not text:
|
25 |
+
return ''
|
26 |
+
access_key_id, access_key_secret, region = self._get_config()
|
27 |
+
from aliyunsdkcore.client import AcsClient
|
28 |
+
from aliyunsdkalimt.request.v20181012 import TranslateRequest
|
29 |
+
|
30 |
+
client = AcsClient(access_key_id, access_key_secret, region)
|
31 |
+
request = TranslateRequest.TranslateRequest()
|
32 |
+
request.set_SourceLanguage(self.from_lang)
|
33 |
+
request.set_Scene("general")
|
34 |
+
request.set_SourceText(text)
|
35 |
+
request.set_FormatType("text") # 翻译文本的格式
|
36 |
+
request.set_TargetLanguage(self.to_lang)
|
37 |
+
request.set_method("POST")
|
38 |
+
response = client.do_action_with_exception(request)
|
39 |
+
result = json.loads(response)
|
40 |
+
if 'Code' not in result:
|
41 |
+
raise Exception(get_lang('no_response_from', {'0': 'Alibaba'}))
|
42 |
+
if result['Code'] != '200':
|
43 |
+
raise Exception(result['Message'])
|
44 |
+
if 'Translated' not in result['Data']:
|
45 |
+
raise Exception(get_lang('no_response_from', {'0': 'Alibaba'}))
|
46 |
+
return result['Data']['Translated']
|
47 |
+
|
48 |
+
def translate_batch(self, texts):
|
49 |
+
if not texts:
|
50 |
+
return []
|
51 |
+
access_key_id, access_key_secret, region = self._get_config()
|
52 |
+
from aliyunsdkcore.client import AcsClient
|
53 |
+
from aliyunsdkalimt.request.v20181012 import GetBatchTranslateRequest
|
54 |
+
|
55 |
+
results = []
|
56 |
+
|
57 |
+
concurrent = self.get_concurrent()
|
58 |
+
texts_len = len(texts)
|
59 |
+
group_num = ceil(texts_len / concurrent)
|
60 |
+
for i in range(group_num):
|
61 |
+
start = i * concurrent
|
62 |
+
end = (i + 1) * concurrent
|
63 |
+
if end > texts_len:
|
64 |
+
end = texts_len
|
65 |
+
group_texts = texts[start:end]
|
66 |
+
source_texts = {}
|
67 |
+
dist_texts = {}
|
68 |
+
for i in range(len(group_texts)):
|
69 |
+
source_texts[str(i)] = group_texts[i]
|
70 |
+
dist_texts[str(i)] = ''
|
71 |
+
|
72 |
+
client = AcsClient(access_key_id, access_key_secret, region)
|
73 |
+
request = GetBatchTranslateRequest.GetBatchTranslateRequest()
|
74 |
+
request.set_SourceLanguage(self.from_lang)
|
75 |
+
request.set_Scene("general")
|
76 |
+
request.set_SourceText(source_texts)
|
77 |
+
request.set_FormatType("text")
|
78 |
+
request.set_TargetLanguage(self.to_lang)
|
79 |
+
request.set_ApiType("translate_standard")
|
80 |
+
request.set_method("POST")
|
81 |
+
response = client.do_action_with_exception(request)
|
82 |
+
result = json.loads(response)
|
83 |
+
if 'Code' not in result:
|
84 |
+
raise Exception(get_lang('no_response_from', {'0': 'Alibaba'}))
|
85 |
+
if result['Code'] != '200':
|
86 |
+
raise Exception(result['Message'])
|
87 |
+
for item in result['TranslatedList']:
|
88 |
+
index = item['index']
|
89 |
+
if item['code'] == '200':
|
90 |
+
dist_texts[index] = item['translated']
|
91 |
+
|
92 |
+
for i in range(len(group_texts)):
|
93 |
+
results.append(dist_texts[str(i)])
|
94 |
+
|
95 |
+
return results
|
scripts/physton_prompt/translator/amazon_translator.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
from scripts.physton_prompt.get_lang import get_lang
|
3 |
+
|
4 |
+
|
5 |
+
class AmazonTranslator(BaseTranslator):
|
6 |
+
def __init__(self):
|
7 |
+
super().__init__('amazon')
|
8 |
+
|
9 |
+
def translate(self, text):
|
10 |
+
if not text:
|
11 |
+
return ''
|
12 |
+
api_key_id = self.api_config.get('api_key_id', '')
|
13 |
+
api_key_secret = self.api_config.get('api_key_secret', '')
|
14 |
+
region = self.api_config.get('region', '')
|
15 |
+
if not api_key_id:
|
16 |
+
raise Exception(get_lang('is_required', {'0': 'API Key ID'}))
|
17 |
+
if not api_key_secret:
|
18 |
+
raise Exception(get_lang('is_required', {'0': 'API Key Secret'}))
|
19 |
+
if not region:
|
20 |
+
raise Exception(get_lang('is_required', {'0': 'Region'}))
|
21 |
+
|
22 |
+
import boto3
|
23 |
+
translate = boto3.client(service_name='translate', region_name=region, use_ssl=True,
|
24 |
+
aws_access_key_id=api_key_id, aws_secret_access_key=api_key_secret)
|
25 |
+
result = translate.translate_text(Text=text, SourceLanguageCode=self.from_lang, TargetLanguageCode=self.to_lang)
|
26 |
+
if 'TranslatedText' not in result:
|
27 |
+
raise Exception(get_lang('no_response_from', {'0': 'Amazon'}))
|
28 |
+
return result['TranslatedText']
|
scripts/physton_prompt/translator/baidu_translator.py
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import requests
|
3 |
+
import hashlib
|
4 |
+
import random
|
5 |
+
from scripts.physton_prompt.get_lang import get_lang
|
6 |
+
|
7 |
+
|
8 |
+
class BaiduTranslator(BaseTranslator):
|
9 |
+
def __init__(self):
|
10 |
+
super().__init__('baidu')
|
11 |
+
|
12 |
+
def translate(self, text):
|
13 |
+
if not text:
|
14 |
+
return ''
|
15 |
+
url = "https://fanyi-api.baidu.com/api/trans/vip/translate"
|
16 |
+
app_id = self.api_config.get('app_id', '')
|
17 |
+
app_secret = self.api_config.get('app_secret', '')
|
18 |
+
if not app_id:
|
19 |
+
raise Exception(get_lang('is_required', {'0': 'APP ID'}))
|
20 |
+
if not app_secret:
|
21 |
+
raise Exception(get_lang('is_required', {'0': 'APP Secret'}))
|
22 |
+
salt = random.randint(32768, 65536)
|
23 |
+
send_text = text
|
24 |
+
if isinstance(text, list):
|
25 |
+
send_text = '\n'.join(send_text)
|
26 |
+
sign = app_id + send_text + str(salt) + app_secret
|
27 |
+
sign = hashlib.md5(sign.encode()).hexdigest()
|
28 |
+
params = {
|
29 |
+
'q': send_text,
|
30 |
+
'from': self.from_lang,
|
31 |
+
'to': self.to_lang,
|
32 |
+
'appid': app_id,
|
33 |
+
'salt': salt,
|
34 |
+
'sign': sign
|
35 |
+
}
|
36 |
+
response = requests.get(url, params=params, timeout=10)
|
37 |
+
result = response.json()
|
38 |
+
if 'error_code' in result:
|
39 |
+
raise Exception(result['error_msg'])
|
40 |
+
if 'trans_result' not in result:
|
41 |
+
raise Exception(get_lang('no_response_from', {'0': 'Baidu'}))
|
42 |
+
translated_text = []
|
43 |
+
for item in result['trans_result']:
|
44 |
+
translated_text.append(item['dst'])
|
45 |
+
if isinstance(text, list):
|
46 |
+
return translated_text
|
47 |
+
else:
|
48 |
+
return '\n'.join(translated_text)
|
49 |
+
|
50 |
+
def translate_batch(self, texts):
|
51 |
+
if not texts:
|
52 |
+
return []
|
53 |
+
for text in texts:
|
54 |
+
text = text.replace('\n', ' ')
|
55 |
+
return self.translate(texts)
|
scripts/physton_prompt/translator/base_tanslator.py
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import time
|
2 |
+
from abc import ABC, abstractmethod
|
3 |
+
from concurrent.futures import ThreadPoolExecutor
|
4 |
+
from math import ceil
|
5 |
+
|
6 |
+
from scripts.physton_prompt.get_lang import get_lang
|
7 |
+
from scripts.physton_prompt.get_translate_apis import get_translate_apis
|
8 |
+
|
9 |
+
|
10 |
+
class BaseTranslator(ABC):
|
11 |
+
from_lang = None
|
12 |
+
to_lang = None
|
13 |
+
api = None
|
14 |
+
api_config = {}
|
15 |
+
api_item = {}
|
16 |
+
|
17 |
+
def __init__(self, api):
|
18 |
+
self.api = api
|
19 |
+
apis = get_translate_apis()
|
20 |
+
find = False
|
21 |
+
for group in apis['apis']:
|
22 |
+
for item in group['children']:
|
23 |
+
if item['key'] == api:
|
24 |
+
find = item
|
25 |
+
break
|
26 |
+
if not find:
|
27 |
+
raise Exception(get_lang('translate_api_not_support'))
|
28 |
+
self.api_item = find
|
29 |
+
|
30 |
+
def set_from_lang(self, from_lang):
|
31 |
+
from_lang = self.api_item['support'].get(from_lang, False)
|
32 |
+
if not from_lang:
|
33 |
+
raise Exception(get_lang('translate_language_not_support'))
|
34 |
+
self.from_lang = from_lang
|
35 |
+
return self
|
36 |
+
|
37 |
+
def set_to_lang(self, to_lang):
|
38 |
+
to_lang = self.api_item['support'].get(to_lang, False)
|
39 |
+
if not to_lang:
|
40 |
+
raise Exception(get_lang('translate_language_not_support'))
|
41 |
+
self.to_lang = to_lang
|
42 |
+
return self
|
43 |
+
|
44 |
+
def set_api_config(self, api_config):
|
45 |
+
self.api_config = api_config
|
46 |
+
return self
|
47 |
+
|
48 |
+
def get_concurrent(self):
|
49 |
+
concurrent = 1
|
50 |
+
if self.api_item.get('concurrent', False):
|
51 |
+
concurrent = self.api_item['concurrent']
|
52 |
+
return concurrent
|
53 |
+
|
54 |
+
@abstractmethod
|
55 |
+
def translate(self, text):
|
56 |
+
pass
|
57 |
+
|
58 |
+
def translate_batch(self, texts):
|
59 |
+
concurrent = self.get_concurrent()
|
60 |
+
texts_len = len(texts)
|
61 |
+
group_num = ceil(texts_len / concurrent)
|
62 |
+
|
63 |
+
# 分组并发翻译,每组完成后等待1秒,然后再进行下一组
|
64 |
+
results = []
|
65 |
+
with ThreadPoolExecutor(max_workers=concurrent) as executor:
|
66 |
+
for i in range(group_num):
|
67 |
+
group_texts = texts[i * concurrent: (i + 1) * concurrent]
|
68 |
+
texts_dict = {}
|
69 |
+
futures = []
|
70 |
+
for i in range(len(group_texts)):
|
71 |
+
text = group_texts[i]
|
72 |
+
texts_dict[str(i)] = ''
|
73 |
+
future = executor.submit(self.translate, text)
|
74 |
+
futures.append(future)
|
75 |
+
|
76 |
+
for i in range(len(futures)):
|
77 |
+
future = futures[i]
|
78 |
+
text_dict = texts_dict
|
79 |
+
future.result()
|
80 |
+
text_dict[str(i)] = future.result()
|
81 |
+
|
82 |
+
for i in range(len(texts_dict)):
|
83 |
+
results.append(texts_dict[str(i)])
|
84 |
+
|
85 |
+
time.sleep(1)
|
86 |
+
|
87 |
+
return results
|
scripts/physton_prompt/translator/caiyun_translator.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import uuid
|
3 |
+
import requests
|
4 |
+
import json
|
5 |
+
from scripts.physton_prompt.get_lang import get_lang
|
6 |
+
|
7 |
+
|
8 |
+
class CaiyunTranslator(BaseTranslator):
|
9 |
+
def __init__(self):
|
10 |
+
super().__init__('caiyun')
|
11 |
+
|
12 |
+
def translate(self, text):
|
13 |
+
if not text:
|
14 |
+
return ''
|
15 |
+
url = 'http://api.interpreter.caiyunai.com/v1/translator'
|
16 |
+
token = self.api_config.get('token', '')
|
17 |
+
if not token:
|
18 |
+
raise Exception(get_lang('is_required', {'0': 'Token'}))
|
19 |
+
|
20 |
+
payload = {
|
21 |
+
"source": text,
|
22 |
+
"trans_type": f'{self.from_lang}2{self.to_lang}',
|
23 |
+
"request_id": str(uuid.uuid4()),
|
24 |
+
"detect": True,
|
25 |
+
}
|
26 |
+
|
27 |
+
headers = {
|
28 |
+
"content-type": "application/json",
|
29 |
+
"x-authorization": "token " + token,
|
30 |
+
}
|
31 |
+
|
32 |
+
response = requests.post(url, data=json.dumps(payload), headers=headers)
|
33 |
+
if not response.text:
|
34 |
+
raise Exception(get_lang('response_is_empty', {'0': 'caiyun'}))
|
35 |
+
result = response.json()
|
36 |
+
if 'message' in result:
|
37 |
+
raise Exception(result['message'])
|
38 |
+
if 'target' not in result:
|
39 |
+
raise Exception(get_lang('no_response_from', {'0': 'caiyun'}))
|
40 |
+
return result['target']
|
scripts/physton_prompt/translator/deepl_translator.py
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import requests
|
3 |
+
from scripts.physton_prompt.get_lang import get_lang
|
4 |
+
|
5 |
+
|
6 |
+
class DeeplTranslator(BaseTranslator):
|
7 |
+
def __init__(self):
|
8 |
+
super().__init__('deepl')
|
9 |
+
|
10 |
+
def translate(self, text):
|
11 |
+
if not text:
|
12 |
+
if isinstance(text, list):
|
13 |
+
return []
|
14 |
+
else:
|
15 |
+
return ''
|
16 |
+
url = 'https://api-free.deepl.com/v2/translate'
|
17 |
+
api_key = self.api_config.get('api_key', '')
|
18 |
+
if not api_key:
|
19 |
+
raise Exception(get_lang('is_required', {'0': 'API Key'}))
|
20 |
+
headers = {"Authorization": f"DeepL-Auth-Key {api_key}"}
|
21 |
+
data = {
|
22 |
+
'text': text,
|
23 |
+
'source_lang': self.from_lang,
|
24 |
+
'target_lang': self.to_lang
|
25 |
+
}
|
26 |
+
|
27 |
+
response = requests.post(url, headers=headers, data=data, timeout=10)
|
28 |
+
if response.status_code != 200:
|
29 |
+
raise Exception(get_lang('request_error', {'0': 'DeepL'}))
|
30 |
+
if not response.text:
|
31 |
+
raise Exception(get_lang('response_is_empty', {'0': 'DeepL'}))
|
32 |
+
result = response.json()
|
33 |
+
if 'message' in result:
|
34 |
+
raise Exception(result['message'])
|
35 |
+
if 'translations' not in result:
|
36 |
+
raise Exception(get_lang('no_response_from', {'0': 'DeepL'}))
|
37 |
+
if isinstance(text, list):
|
38 |
+
results = []
|
39 |
+
for item in result['translations']:
|
40 |
+
results.append(item['text'])
|
41 |
+
return results
|
42 |
+
else:
|
43 |
+
return result['translations'][0]['text']
|
44 |
+
|
45 |
+
def translate_batch(self, texts):
|
46 |
+
return self.translate(texts)
|
scripts/physton_prompt/translator/google_tanslator.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import requests
|
3 |
+
from scripts.physton_prompt.get_lang import get_lang
|
4 |
+
|
5 |
+
|
6 |
+
class GoogleTranslator(BaseTranslator):
|
7 |
+
def __init__(self):
|
8 |
+
super().__init__('google')
|
9 |
+
|
10 |
+
def translate(self, text):
|
11 |
+
if not text:
|
12 |
+
return ''
|
13 |
+
url = 'https://translation.googleapis.com/language/translate/v2/'
|
14 |
+
api_key = self.api_config.get('api_key', '')
|
15 |
+
if not api_key:
|
16 |
+
raise Exception(get_lang('is_required', {'0': 'API Key'}))
|
17 |
+
params = {
|
18 |
+
'key': api_key,
|
19 |
+
'q': text,
|
20 |
+
'source': self.from_lang,
|
21 |
+
'target': self.to_lang,
|
22 |
+
'format': 'text'
|
23 |
+
}
|
24 |
+
response = requests.get(url, params=params, timeout=10)
|
25 |
+
result = response.json()
|
26 |
+
if 'error' in result:
|
27 |
+
raise Exception(result['error']['message'])
|
28 |
+
if 'data' not in result:
|
29 |
+
raise Exception(get_lang('no_response_from', {'0': 'Google'}))
|
30 |
+
if 'translations' not in result['data']:
|
31 |
+
raise Exception(get_lang('no_response_from', {'0': 'Google'}))
|
32 |
+
return result['data']['translations'][0]['translatedText']
|
scripts/physton_prompt/translator/iflytekV1_translator.py
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import requests
|
3 |
+
import datetime
|
4 |
+
import hashlib
|
5 |
+
import base64
|
6 |
+
import hmac
|
7 |
+
import json
|
8 |
+
from scripts.physton_prompt.get_lang import get_lang
|
9 |
+
|
10 |
+
|
11 |
+
class IflytekV1Translator(BaseTranslator):
|
12 |
+
def __init__(self):
|
13 |
+
super().__init__('iflytekV1')
|
14 |
+
|
15 |
+
def translate(self, text):
|
16 |
+
if not text:
|
17 |
+
return ''
|
18 |
+
app_id = self.api_config.get('app_id', '')
|
19 |
+
if not app_id:
|
20 |
+
raise Exception(get_lang('is_required', {'0': 'APP ID'}))
|
21 |
+
api_secret = self.api_config.get('api_secret', '')
|
22 |
+
if not api_secret:
|
23 |
+
raise Exception(get_lang('is_required', {'0': 'API Secret'}))
|
24 |
+
api_key = self.api_config.get('api_key', '')
|
25 |
+
if not api_key:
|
26 |
+
raise Exception(get_lang('is_required', {'0': 'API Key'}))
|
27 |
+
|
28 |
+
response = translate(text, From=self.from_lang, To=self.to_lang, APPID=app_id, Secret=api_secret, APIKey=api_key)
|
29 |
+
if response.status_code != 200:
|
30 |
+
raise Exception(get_lang('request_error', {'0': 'iflytekV1'}))
|
31 |
+
if not response.text:
|
32 |
+
raise Exception(get_lang('response_is_empty', {'0': 'iflytekV1'}))
|
33 |
+
result = response.json()
|
34 |
+
if 'code' not in result:
|
35 |
+
raise Exception(get_lang('no_response_from', {'0': 'iflytekV1'}))
|
36 |
+
if result['code'] != 0:
|
37 |
+
raise Exception(result['message'])
|
38 |
+
return result['data']['result']['trans_result']['dst']
|
39 |
+
|
40 |
+
|
41 |
+
def hashlib_256(res):
|
42 |
+
m = hashlib.sha256(bytes(res.encode(encoding='utf-8'))).digest()
|
43 |
+
result = "SHA-256=" + base64.b64encode(m).decode(encoding='utf-8')
|
44 |
+
return result
|
45 |
+
|
46 |
+
def httpdate(dt):
|
47 |
+
"""
|
48 |
+
Return a string representation of a date according to RFC 1123
|
49 |
+
(HTTP/1.1).
|
50 |
+
|
51 |
+
The supplied date must be in UTC.
|
52 |
+
|
53 |
+
"""
|
54 |
+
weekday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()]
|
55 |
+
month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
|
56 |
+
"Oct", "Nov", "Dec"][dt.month - 1]
|
57 |
+
return "%s, %02d %s %04d %02d:%02d:%02d GMT" % (weekday, dt.day, month,
|
58 |
+
dt.year, dt.hour, dt.minute, dt.second)
|
59 |
+
|
60 |
+
def translate(Text, From, To, APPID, Secret, APIKey, Host="itrans.xfyun.cn"):
|
61 |
+
RequestUri = "/v2/its"
|
62 |
+
url="https://"+Host+RequestUri
|
63 |
+
HttpMethod = "POST"
|
64 |
+
Algorithm = "hmac-sha256"
|
65 |
+
HttpProto = "HTTP/1.1"
|
66 |
+
|
67 |
+
# 设置当前时间
|
68 |
+
curTime_utc = datetime.datetime.utcnow()
|
69 |
+
Date = httpdate(curTime_utc)
|
70 |
+
# 设置业务参数
|
71 |
+
# 语种列表参数值请参照接口文档:https://www.xfyun.cn/doc/nlp/xftrans/API.html
|
72 |
+
BusinessArgs={
|
73 |
+
"from":From,
|
74 |
+
"to": To,
|
75 |
+
}
|
76 |
+
|
77 |
+
content = str(base64.b64encode(Text.encode('utf-8')), 'utf-8')
|
78 |
+
postdata = {
|
79 |
+
"common": {"app_id": APPID},
|
80 |
+
"business": BusinessArgs,
|
81 |
+
"data": {
|
82 |
+
"text": content,
|
83 |
+
}
|
84 |
+
}
|
85 |
+
body = json.dumps(postdata)
|
86 |
+
|
87 |
+
digest = hashlib_256(body)
|
88 |
+
signatureStr = "host: " + Host + "\n"
|
89 |
+
signatureStr += "date: " + Date + "\n"
|
90 |
+
signatureStr += HttpMethod + " " + RequestUri \
|
91 |
+
+ " " + HttpProto + "\n"
|
92 |
+
signatureStr += "digest: " + digest
|
93 |
+
signature = hmac.new(bytes(Secret.encode(encoding='utf-8')),
|
94 |
+
bytes(signatureStr.encode(encoding='utf-8')),
|
95 |
+
digestmod=hashlib.sha256).digest()
|
96 |
+
sign = base64.b64encode(signature).decode(encoding='utf-8')
|
97 |
+
|
98 |
+
authHeader = 'api_key="%s", algorithm="%s", ' \
|
99 |
+
'headers="host date request-line digest", ' \
|
100 |
+
'signature="%s"' \
|
101 |
+
% (APIKey, Algorithm, sign)
|
102 |
+
headers = {
|
103 |
+
"Content-Type": "application/json",
|
104 |
+
"Accept": "application/json",
|
105 |
+
"Method": "POST",
|
106 |
+
"Host": Host,
|
107 |
+
"Date": Date,
|
108 |
+
"Digest": digest,
|
109 |
+
"Authorization": authHeader
|
110 |
+
}
|
111 |
+
|
112 |
+
response = requests.post(url, data=body, headers=headers,timeout=60)
|
113 |
+
return response
|
scripts/physton_prompt/translator/iflytekV2_translator.py
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
from datetime import datetime
|
3 |
+
from wsgiref.handlers import format_date_time
|
4 |
+
from time import mktime
|
5 |
+
import hashlib
|
6 |
+
import base64
|
7 |
+
import hmac
|
8 |
+
from urllib.parse import urlencode
|
9 |
+
import json
|
10 |
+
import requests
|
11 |
+
from scripts.physton_prompt.get_lang import get_lang
|
12 |
+
|
13 |
+
|
14 |
+
class IflytekV2Translator(BaseTranslator):
|
15 |
+
def __init__(self):
|
16 |
+
super().__init__('iflytekV2')
|
17 |
+
|
18 |
+
def translate(self, text):
|
19 |
+
if not text:
|
20 |
+
return ''
|
21 |
+
app_id = self.api_config.get('app_id', '')
|
22 |
+
if not app_id:
|
23 |
+
raise Exception(get_lang('is_required', {'0': 'APP ID'}))
|
24 |
+
api_secret = self.api_config.get('api_secret', '')
|
25 |
+
if not api_secret:
|
26 |
+
raise Exception(get_lang('is_required', {'0': 'API Secret'}))
|
27 |
+
api_key = self.api_config.get('api_key', '')
|
28 |
+
if not api_key:
|
29 |
+
raise Exception(get_lang('is_required', {'0': 'API Key'}))
|
30 |
+
|
31 |
+
response = translate(text, From=self.from_lang, To=self.to_lang, APPId=app_id, APISecret=api_secret, APIKey=api_key)
|
32 |
+
if response.status_code != 200:
|
33 |
+
raise Exception(get_lang('request_error', {'0': 'iflytekV1'}))
|
34 |
+
if not response.text:
|
35 |
+
raise Exception(get_lang('response_is_empty', {'0': 'iflytekV1'}))
|
36 |
+
result = json.loads(response.content.decode())
|
37 |
+
if 'header' not in result:
|
38 |
+
raise Exception(get_lang('no_response_from', {'0': 'iflytekV1'}))
|
39 |
+
result = json.loads(response.content.decode())
|
40 |
+
if 'code' not in result['header']:
|
41 |
+
raise Exception(get_lang('no_response_from', {'0': 'iflytekV1'}))
|
42 |
+
if result['header']['code'] != 0:
|
43 |
+
raise Exception(result['header']['message'])
|
44 |
+
restul_decode = base64.b64decode(result['payload']['result']['text']).decode()
|
45 |
+
result_json = json.loads(restul_decode)
|
46 |
+
if 'trans_result' not in result_json:
|
47 |
+
raise Exception(get_lang('no_response_from', {'0': 'iflytekV1'}))
|
48 |
+
return result_json['trans_result']['dst']
|
49 |
+
|
50 |
+
class Url:
|
51 |
+
def __init__(self, host, path, schema):
|
52 |
+
self.host = host
|
53 |
+
self.path = path
|
54 |
+
self.schema = schema
|
55 |
+
pass
|
56 |
+
|
57 |
+
# calculate sha256 and encode to base64
|
58 |
+
def sha256base64(data):
|
59 |
+
sha256 = hashlib.sha256()
|
60 |
+
sha256.update(data)
|
61 |
+
digest = base64.b64encode(sha256.digest()).decode(encoding='utf-8')
|
62 |
+
return digest
|
63 |
+
|
64 |
+
def parse_url(requset_url):
|
65 |
+
stidx = requset_url.index("://")
|
66 |
+
host = requset_url[stidx + 3:]
|
67 |
+
schema = requset_url[:stidx + 3]
|
68 |
+
edidx = host.index("/")
|
69 |
+
if edidx <= 0:
|
70 |
+
raise Exception("invalid request url:" + requset_url)
|
71 |
+
path = host[edidx:]
|
72 |
+
host = host[:edidx]
|
73 |
+
u = Url(host, path, schema)
|
74 |
+
return u
|
75 |
+
|
76 |
+
# build websocket auth request url
|
77 |
+
def assemble_ws_auth_url(requset_url, method="POST", api_key="", api_secret=""):
|
78 |
+
u = parse_url(requset_url)
|
79 |
+
host = u.host
|
80 |
+
path = u.path
|
81 |
+
now = datetime.now()
|
82 |
+
date = format_date_time(mktime(now.timetuple()))
|
83 |
+
signature_origin = "host: {}\ndate: {}\n{} {} HTTP/1.1".format(host, date, method, path)
|
84 |
+
signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
|
85 |
+
digestmod=hashlib.sha256).digest()
|
86 |
+
signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
|
87 |
+
authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
|
88 |
+
api_key, "hmac-sha256", "host date request-line", signature_sha)
|
89 |
+
authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
|
90 |
+
values = {
|
91 |
+
"host": host,
|
92 |
+
"date": date,
|
93 |
+
"authorization": authorization
|
94 |
+
}
|
95 |
+
|
96 |
+
return requset_url + "?" + urlencode(values)
|
97 |
+
|
98 |
+
def translate(Text, From, To, APPId, APISecret, APIKey, Host="itrans.xf-yun.com"):
|
99 |
+
RequestUri = "/v1/its"
|
100 |
+
url="https://"+Host+RequestUri
|
101 |
+
|
102 |
+
body = {
|
103 |
+
"header": {
|
104 |
+
"app_id": APPId,
|
105 |
+
"status": 3,
|
106 |
+
},
|
107 |
+
"parameter": {
|
108 |
+
"its": {
|
109 |
+
"from": From,
|
110 |
+
"to": To,
|
111 |
+
"result": {}
|
112 |
+
}
|
113 |
+
},
|
114 |
+
"payload": {
|
115 |
+
"input_data": {
|
116 |
+
"encoding": "utf8",
|
117 |
+
"status": 3,
|
118 |
+
"text": base64.b64encode(Text.encode("utf-8")).decode('utf-8')
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
request_url = assemble_ws_auth_url(url, "POST", APIKey, APISecret)
|
124 |
+
|
125 |
+
headers = {'content-type': "application/json", 'host': 'itrans.xf-yun.com', 'app_id': APPId}
|
126 |
+
# print(request_url)
|
127 |
+
response = requests.post(request_url, data=json.dumps(body), headers=headers)
|
128 |
+
return response
|
scripts/physton_prompt/translator/mbart50_translator.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
from scripts.physton_prompt.get_lang import get_lang
|
3 |
+
from scripts.physton_prompt.mbart50 import initialize as mbart50_initialize, translate as mbart50_translate
|
4 |
+
|
5 |
+
|
6 |
+
class MBart50Translator(BaseTranslator):
|
7 |
+
def __init__(self):
|
8 |
+
super().__init__('mbart50')
|
9 |
+
|
10 |
+
def translate(self, text):
|
11 |
+
if not text:
|
12 |
+
if isinstance(text, list):
|
13 |
+
return []
|
14 |
+
else:
|
15 |
+
return ''
|
16 |
+
|
17 |
+
result = mbart50_translate(text=text, src_lang=self.from_lang, target_lang=self.to_lang)
|
18 |
+
if not result:
|
19 |
+
raise Exception(get_lang('response_is_empty', {'0': 'mbart50'}))
|
20 |
+
|
21 |
+
if isinstance(text, list):
|
22 |
+
return result
|
23 |
+
else:
|
24 |
+
return result[0]
|
25 |
+
|
26 |
+
def translate_batch(self, texts):
|
27 |
+
return self.translate(texts)
|
scripts/physton_prompt/translator/microsoft_translator.py
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import uuid
|
3 |
+
import requests
|
4 |
+
from scripts.physton_prompt.get_lang import get_lang
|
5 |
+
|
6 |
+
|
7 |
+
class MicrosoftTranslator(BaseTranslator):
|
8 |
+
def __init__(self):
|
9 |
+
super().__init__('microsoft')
|
10 |
+
|
11 |
+
def translate(self, text):
|
12 |
+
if not text:
|
13 |
+
if isinstance(text, list):
|
14 |
+
return []
|
15 |
+
else:
|
16 |
+
return ''
|
17 |
+
url = 'https://api.cognitive.microsofttranslator.com/translate'
|
18 |
+
api_key = self.api_config.get('api_key', '')
|
19 |
+
region = self.api_config.get('region', '')
|
20 |
+
if not api_key:
|
21 |
+
raise Exception(get_lang('is_required', {'0': 'API Key'}))
|
22 |
+
if not region:
|
23 |
+
raise Exception(get_lang('is_required', {'0': 'Region'}))
|
24 |
+
params = {
|
25 |
+
'api-version': '3.0',
|
26 |
+
'from': self.from_lang,
|
27 |
+
'to': self.to_lang
|
28 |
+
}
|
29 |
+
headers = {
|
30 |
+
'Ocp-Apim-Subscription-Key': api_key,
|
31 |
+
'Ocp-Apim-Subscription-Region': region,
|
32 |
+
'Content-type': 'application/json',
|
33 |
+
'X-ClientTraceId': str(uuid.uuid4())
|
34 |
+
}
|
35 |
+
|
36 |
+
body = []
|
37 |
+
if isinstance(text, list):
|
38 |
+
for item in text:
|
39 |
+
body.append({'text': item})
|
40 |
+
else:
|
41 |
+
body.append({'text': text})
|
42 |
+
|
43 |
+
response = requests.post(url, params=params, headers=headers, json=body, timeout=10)
|
44 |
+
result = response.json()
|
45 |
+
if 'error' in result:
|
46 |
+
raise Exception(result['error']['message'])
|
47 |
+
if len(result) == 0:
|
48 |
+
raise Exception(get_lang('no_response_from', {'0': 'Microsoft'}))
|
49 |
+
|
50 |
+
if isinstance(text, list):
|
51 |
+
return [item['translations'][0]['text'] for item in result]
|
52 |
+
else:
|
53 |
+
return result[0]['translations'][0]['text']
|
54 |
+
|
55 |
+
def translate_batch(self, texts):
|
56 |
+
return self.translate(texts)
|
scripts/physton_prompt/translator/mymemory_translator.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import uuid
|
3 |
+
import requests
|
4 |
+
from scripts.physton_prompt.get_lang import get_lang
|
5 |
+
|
6 |
+
|
7 |
+
class MyMemoryTranslator(BaseTranslator):
|
8 |
+
def __init__(self):
|
9 |
+
super().__init__('myMemory_free')
|
10 |
+
|
11 |
+
def translate(self, text):
|
12 |
+
if not text:
|
13 |
+
return ''
|
14 |
+
url = 'https://api.mymemory.translated.net/get'
|
15 |
+
api_key = self.api_config.get('api_key', '')
|
16 |
+
params = {
|
17 |
+
'q': text,
|
18 |
+
'langpair': f'{self.from_lang}|{self.to_lang}',
|
19 |
+
}
|
20 |
+
if api_key:
|
21 |
+
params['key'] = api_key
|
22 |
+
|
23 |
+
response = requests.get(url, params=params)
|
24 |
+
if response.status_code != 200:
|
25 |
+
raise Exception(get_lang('request_error', {'0': 'myMemory'}))
|
26 |
+
if not response.text:
|
27 |
+
raise Exception(get_lang('response_is_empty', {'0': 'myMemory'}))
|
28 |
+
result = response.json()
|
29 |
+
if 'responseStatus' not in result:
|
30 |
+
raise Exception(get_lang('no_response_from', {'0': 'myMemory'}))
|
31 |
+
if result['responseStatus'] != 200:
|
32 |
+
raise Exception(result['responseDetails'])
|
33 |
+
if 'responseData' not in result:
|
34 |
+
raise Exception(get_lang('no_response_from', {'0': 'myMemory'}))
|
35 |
+
if 'translatedText' not in result['responseData']:
|
36 |
+
raise Exception(get_lang('no_response_from', {'0': 'myMemory'}))
|
37 |
+
return result['responseData']['translatedText']
|
scripts/physton_prompt/translator/niutrans_translator.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import uuid
|
3 |
+
import requests
|
4 |
+
from scripts.physton_prompt.get_lang import get_lang
|
5 |
+
|
6 |
+
|
7 |
+
class NiutransTranslator(BaseTranslator):
|
8 |
+
def __init__(self):
|
9 |
+
super().__init__('niutrans')
|
10 |
+
|
11 |
+
def translate(self, text):
|
12 |
+
if not text:
|
13 |
+
return ''
|
14 |
+
url = 'https://api.niutrans.com/NiuTransServer/translation'
|
15 |
+
api_key = self.api_config.get('api_key', '')
|
16 |
+
if not api_key:
|
17 |
+
raise Exception(get_lang('is_required', {'0': 'API Key'}))
|
18 |
+
data = {
|
19 |
+
'from': self.from_lang,
|
20 |
+
'to': self.to_lang,
|
21 |
+
'apikey': api_key,
|
22 |
+
'src_text': text,
|
23 |
+
}
|
24 |
+
|
25 |
+
response = requests.post(url, data=data)
|
26 |
+
if response.status_code != 200:
|
27 |
+
raise Exception(get_lang('request_error', {'0': 'niutrans'}))
|
28 |
+
if not response.text:
|
29 |
+
raise Exception(get_lang('response_is_empty', {'0': 'niutrans'}))
|
30 |
+
result = response.json()
|
31 |
+
if 'error_msg' in result:
|
32 |
+
raise Exception(result['error_msg'])
|
33 |
+
if 'tgt_text' not in result:
|
34 |
+
raise Exception(get_lang('no_response_from', {'0': 'niutrans'}))
|
35 |
+
return result['tgt_text']
|
scripts/physton_prompt/translator/openai_translator.py
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
2 |
+
import json
|
3 |
+
from scripts.physton_prompt.get_lang import get_lang
|
4 |
+
|
5 |
+
|
6 |
+
class OpenaiTranslator(BaseTranslator):
|
7 |
+
def __init__(self):
|
8 |
+
super().__init__('openai')
|
9 |
+
|
10 |
+
def translate(self, text):
|
11 |
+
if not text:
|
12 |
+
if isinstance(text, list):
|
13 |
+
return []
|
14 |
+
else:
|
15 |
+
return ''
|
16 |
+
import openai
|
17 |
+
openai.api_base = self.api_config.get('api_base', 'https://api.openai.com/v1')
|
18 |
+
openai.api_key = self.api_config.get('api_key', '')
|
19 |
+
model = self.api_config.get('model', 'gpt-3.5-turbo')
|
20 |
+
if not openai.api_key:
|
21 |
+
raise Exception(get_lang('is_required', {'0': 'API Key'}))
|
22 |
+
|
23 |
+
body = []
|
24 |
+
if isinstance(text, list):
|
25 |
+
for item in text:
|
26 |
+
body.append({'text': item})
|
27 |
+
else:
|
28 |
+
body.append({'text': text})
|
29 |
+
|
30 |
+
body_str = json.dumps(body, ensure_ascii=False)
|
31 |
+
|
32 |
+
messages = [
|
33 |
+
{"role": "system", "content": "You are a translator assistant."},
|
34 |
+
{
|
35 |
+
"role": "user",
|
36 |
+
"content": f"You are a translator assistant. Please translate the following JSON data {self.to_lang}. Preserve the original format. Only return the translation result, without any additional content or annotations. If the prompt word is in the target language, please send it to me unchanged:\n{body_str}"
|
37 |
+
},
|
38 |
+
]
|
39 |
+
completion = openai.ChatCompletion.create(model=model, messages=messages, timeout=60)
|
40 |
+
if len(completion.choices) == 0:
|
41 |
+
raise Exception(get_lang('no_response_from', {'0': 'OpenAI'}))
|
42 |
+
content = completion.choices[0].message.content
|
43 |
+
try:
|
44 |
+
# 找到第一个[,然后找到最后一个],截取中间的内容
|
45 |
+
start = content.index('[')
|
46 |
+
end = content.rindex(']')
|
47 |
+
if start == -1 or end == -1:
|
48 |
+
raise Exception(get_lang('response_error', {'0': 'OpenAI'}))
|
49 |
+
result_json = '[' + content[start + 1:end] + ']'
|
50 |
+
# 解析json
|
51 |
+
result = json.loads(result_json)
|
52 |
+
if isinstance(text, list):
|
53 |
+
return [item['text'] for item in result]
|
54 |
+
else:
|
55 |
+
return result[0]['text']
|
56 |
+
except Exception as e:
|
57 |
+
raise Exception(get_lang('response_error', {'0': 'OpenAI'}))
|
58 |
+
|
59 |
+
def translate_batch(self, texts):
|
60 |
+
return self.translate(texts)
|
scripts/physton_prompt/translator/tencent_translator.py
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import hashlib
|
2 |
+
import hmac
|
3 |
+
import json
|
4 |
+
import time
|
5 |
+
from datetime import datetime
|
6 |
+
|
7 |
+
import requests
|
8 |
+
|
9 |
+
from scripts.physton_prompt.get_lang import get_lang
|
10 |
+
from scripts.physton_prompt.translator.base_tanslator import BaseTranslator
|
11 |
+
|
12 |
+
|
13 |
+
class TencentTranslator(BaseTranslator):
|
14 |
+
def __init__(self):
|
15 |
+
super().__init__('tencent')
|
16 |
+
|
17 |
+
def _get_config(self):
|
18 |
+
secret_id = self.api_config.get('secret_id', '')
|
19 |
+
secret_key = self.api_config.get('secret_key', '')
|
20 |
+
region = self.api_config.get('region', 'ap-shanghai')
|
21 |
+
if not secret_id:
|
22 |
+
raise Exception(get_lang('is_required', {'0': 'Secret ID'}))
|
23 |
+
if not secret_key:
|
24 |
+
raise Exception(get_lang('is_required', {'0': 'Secret Key'}))
|
25 |
+
if not region:
|
26 |
+
raise Exception(get_lang('is_required', {'0': 'Region'}))
|
27 |
+
return secret_id, secret_key, region
|
28 |
+
|
29 |
+
def translate(self, text):
|
30 |
+
if not text:
|
31 |
+
return ''
|
32 |
+
secret_id, secret_key, region = self._get_config()
|
33 |
+
params = {
|
34 |
+
'SourceText': text,
|
35 |
+
'Source': self.from_lang,
|
36 |
+
'Target': self.to_lang,
|
37 |
+
'ProjectId': 0
|
38 |
+
}
|
39 |
+
res = sign_tencent(secret_id, secret_key, region, params)
|
40 |
+
response = requests.post(res['url'], json=params, timeout=10, headers=res['headers'])
|
41 |
+
result = response.json()
|
42 |
+
if 'Response' not in result:
|
43 |
+
raise Exception(get_lang('no_response_from', {'0': 'Tencent'}))
|
44 |
+
if 'TargetText' not in result['Response']:
|
45 |
+
raise Exception(get_lang('no_response_from', {'0': 'Tencent'}))
|
46 |
+
return result['Response']['TargetText']
|
47 |
+
|
48 |
+
def translate_batch(self, texts):
|
49 |
+
if not texts:
|
50 |
+
return []
|
51 |
+
secret_id, secret_key, region = self._get_config()
|
52 |
+
params = {
|
53 |
+
'SourceTextList': texts,
|
54 |
+
'Source': self.from_lang,
|
55 |
+
'Target': self.to_lang,
|
56 |
+
'ProjectId': 0
|
57 |
+
}
|
58 |
+
res = sign_tencent(secret_id, secret_key, region, params, 'TextTranslateBatch')
|
59 |
+
response = requests.post(res['url'], json=params, timeout=10, headers=res['headers'])
|
60 |
+
result = response.json()
|
61 |
+
if 'Response' not in result:
|
62 |
+
raise Exception(get_lang('no_response_from', {'0': 'Tencent'}))
|
63 |
+
if 'TargetTextList' not in result['Response']:
|
64 |
+
raise Exception(get_lang('no_response_from', {'0': 'Tencent'}))
|
65 |
+
return result['Response']['TargetTextList']
|
66 |
+
|
67 |
+
|
68 |
+
def sign_tencent(secret_id, secret_key, regin, params, action="TextTranslate", version="2018-03-21"):
|
69 |
+
host = 'tmt.tencentcloudapi.com'
|
70 |
+
endpoint = "https://" + host
|
71 |
+
|
72 |
+
service = "tmt"
|
73 |
+
algorithm = "TC3-HMAC-SHA256"
|
74 |
+
timestamp = int(time.time())
|
75 |
+
date = datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d")
|
76 |
+
|
77 |
+
# ************* 步骤 1:拼接规范请求串 *************
|
78 |
+
http_request_method = "POST"
|
79 |
+
canonical_uri = "/"
|
80 |
+
canonical_querystring = ""
|
81 |
+
ct = "application/json; charset=utf-8"
|
82 |
+
payload = json.dumps(params)
|
83 |
+
canonical_headers = "content-type:%s\nhost:%s\nx-tc-action:%s\n" % (ct, host, action.lower())
|
84 |
+
signed_headers = "content-type;host;x-tc-action"
|
85 |
+
hashed_request_payload = hashlib.sha256(payload.encode("utf-8")).hexdigest()
|
86 |
+
canonical_request = (http_request_method + "\n" +
|
87 |
+
canonical_uri + "\n" +
|
88 |
+
canonical_querystring + "\n" +
|
89 |
+
canonical_headers + "\n" +
|
90 |
+
signed_headers + "\n" +
|
91 |
+
hashed_request_payload)
|
92 |
+
|
93 |
+
# ************* 步骤 2:拼接待签名字符串 *************
|
94 |
+
credential_scope = date + "/" + service + "/" + "tc3_request"
|
95 |
+
hashed_canonical_request = hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
|
96 |
+
string_to_sign = (algorithm + "\n" +
|
97 |
+
str(timestamp) + "\n" +
|
98 |
+
credential_scope + "\n" +
|
99 |
+
hashed_canonical_request)
|
100 |
+
|
101 |
+
# ************* 步骤 3:计算签名 *************
|
102 |
+
# 计算签名摘要函数
|
103 |
+
def sign(key, msg):
|
104 |
+
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
|
105 |
+
|
106 |
+
secret_date = sign(("TC3" + secret_key).encode("utf-8"), date)
|
107 |
+
secret_service = sign(secret_date, service)
|
108 |
+
secret_signing = sign(secret_service, "tc3_request")
|
109 |
+
signature = hmac.new(secret_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
|
110 |
+
|
111 |
+
# ************* 步骤 4:拼接 Authorization *************
|
112 |
+
authorization = (algorithm + " " +
|
113 |
+
"Credential=" + secret_id + "/" + credential_scope + ", " +
|
114 |
+
"SignedHeaders=" + signed_headers + ", " +
|
115 |
+
"Signature=" + signature)
|
116 |
+
|
117 |
+
return {
|
118 |
+
"url": endpoint,
|
119 |
+
"headers": {
|
120 |
+
"Authorization": authorization,
|
121 |
+
"Content-Type": ct,
|
122 |
+
"Host": host,
|
123 |
+
"X-TC-Action": action,
|
124 |
+
"X-TC-Timestamp": str(timestamp),
|
125 |
+
"X-TC-Version": version,
|
126 |
+
"X-TC-Region": regin,
|
127 |
+
},
|
128 |
+
}
|