This commit is contained in:
恍兮惚兮 2024-08-15 22:23:31 +08:00
parent 3ee3012733
commit cea81ba61a
5 changed files with 147 additions and 150 deletions

View File

@ -437,6 +437,7 @@ class MAINUI:
): ):
callback = partial( callback = partial(
self.GetTranslationCallback, self.GetTranslationCallback,
embedcallback,
onlytrans, onlytrans,
engine, engine,
self.currentsignature, self.currentsignature,
@ -455,13 +456,14 @@ class MAINUI:
) )
if result: if result:
# 预翻译 # 预翻译
callback(result, embedcallback, 0) callback(result, 0)
else: else:
self.translators[engine].gettask(task) self.translators[engine].gettask(task)
def GetTranslationCallback( def GetTranslationCallback(
self, self,
embedcallback,
onlytrans, onlytrans,
classname, classname,
currentsignature, currentsignature,
@ -470,7 +472,6 @@ class MAINUI:
_showrawfunction_sig, _showrawfunction_sig,
contentraw, contentraw,
res, res,
embedcallback,
iter_res_status, iter_res_status,
): ):
if classname in self.usefultranslators: if classname in self.usefultranslators:

View File

@ -1,6 +1,6 @@
import os, zipfile import os, zipfile
from myutils.utils import getlangsrc, dynamiclink from myutils.utils import dynamiclink
from myutils.config import globalconfig, _TR, getlang_inner2show from myutils.config import _TR, getlang_inner2show
from ocrengines.baseocrclass import baseocr from ocrengines.baseocrclass import baseocr
from ctypes import ( from ctypes import (
CDLL, CDLL,
@ -194,7 +194,7 @@ class OCR(baseocr):
if self._savelang == self.srclang: if self._savelang == self.srclang:
return return
self._ocr = None self._ocr = None
path = "./files/ocr/{}".format(getlangsrc()) path = "./files/ocr/{}".format(self.srclang)
if not ( if not (
os.path.exists(path + "/det.onnx") os.path.exists(path + "/det.onnx")
and os.path.exists(path + "/rec.onnx") and os.path.exists(path + "/rec.onnx")

View File

@ -6,21 +6,19 @@ import zhconv, gobject
import sqlite3, json import sqlite3, json
import functools import functools
from myutils.config import globalconfig, translatorsetting from myutils.config import globalconfig, translatorsetting
from myutils.utils import stringfyerror, autosql, PriorityQueue, getlangtgt from myutils.utils import stringfyerror, autosql, PriorityQueue
from myutils.commonbase import ArgsEmptyExc, commonbase from myutils.commonbase import ArgsEmptyExc, commonbase
class TimeOut(Exception): class Interrupted(Exception):
pass pass
class Threadwithresult(Thread): class Threadwithresult(Thread):
def __init__(self, func, defalut, ignoreexceptions): def __init__(self, func):
super(Threadwithresult, self).__init__() super(Threadwithresult, self).__init__()
self.func = func self.func = func
self.result = defalut self.isInterrupted = True
self.istimeout = True
self.ignoreexceptions = ignoreexceptions
self.exception = None self.exception = None
def run(self): def run(self):
@ -28,31 +26,26 @@ class Threadwithresult(Thread):
self.result = self.func() self.result = self.func()
except Exception as e: except Exception as e:
self.exception = e self.exception = e
self.istimeout = False self.isInterrupted = False
def get_result(self, timeout=1, checktutukufunction=None): def get_result(self, checktutukufunction=None):
# Thread.join(self,timeout) # Thread.join(self,timeout)
# 不再超时等待,只检查是否是最后一个请求,若是则无限等待,否则立即放弃。 # 不再超时等待,只检查是否是最后一个请求,若是则无限等待,否则立即放弃。
while checktutukufunction and checktutukufunction() and self.istimeout: while checktutukufunction and checktutukufunction() and self.isInterrupted:
Thread.join(self, 0.1) Thread.join(self, 0.1)
if self.ignoreexceptions: if self.isInterrupted:
return self.result raise Interrupted()
elif self.exception:
raise self.exception
else: else:
if self.istimeout: return self.result
raise TimeOut()
elif self.exception:
raise self.exception
else:
return self.result
def timeoutfunction( def timeoutfunction(func, checktutukufunction=None):
func, timeout=100, default=None, ignoreexceptions=False, checktutukufunction=None t = Threadwithresult(func)
):
t = Threadwithresult(func, default, ignoreexceptions)
t.start() t.start()
return t.get_result(timeout, checktutukufunction) return t.get_result(checktutukufunction)
class basetrans(commonbase): class basetrans(commonbase):
@ -105,7 +98,6 @@ class basetrans(commonbase):
print_exc() print_exc()
self.lastrequesttime = 0 self.lastrequesttime = 0
self.requestid = 0
self._cache = {} self._cache = {}
self.newline = None self.newline = None
@ -153,11 +145,11 @@ class basetrans(commonbase):
src, trans = task src, trans = task
self.sqlwrite2.execute( self.sqlwrite2.execute(
"DELETE from cache WHERE (srclang,tgtlang,source)=(?,?,?)", "DELETE from cache WHERE (srclang,tgtlang,source)=(?,?,?)",
(self.srclang, self.tgtlang, src), (self.srclang_1, self.tgtlang_1, src),
) )
self.sqlwrite2.execute( self.sqlwrite2.execute(
"INSERT into cache VALUES(?,?,?,?)", "INSERT into cache VALUES(?,?,?,?)",
(self.srclang, self.tgtlang, src, trans), (self.srclang_1, self.tgtlang_1, src, trans),
) )
except: except:
print_exc() print_exc()
@ -175,8 +167,7 @@ class basetrans(commonbase):
@property @property
def needzhconv(self): def needzhconv(self):
# The API does not support direct translation to Traditional Chinese, only Simplified Chinese can be translated first and then converted to Traditional Chinese # The API does not support direct translation to Traditional Chinese, only Simplified Chinese can be translated first and then converted to Traditional Chinese
l = getlangtgt() return self.tgtlang_1 == "cht" and "cht" not in self.langmap()
return l == "cht" and "cht" not in self.langmap()
@property @property
def using(self): def using(self):
@ -185,6 +176,9 @@ class basetrans(commonbase):
@property @property
def transtype(self): def transtype(self):
# free/dev/api/offline/pre # free/dev/api/offline/pre
# dev/offline/pre 无视请求间隔
# pre不使用翻译缓存
# offline不被新的请求打断
return globalconfig["fanyi"][self.typename].get("type", "free") return globalconfig["fanyi"][self.typename].get("type", "free")
def gettask(self, content): def gettask(self, content):
@ -200,8 +194,8 @@ class basetrans(commonbase):
def longtermcacheget(self, src): def longtermcacheget(self, src):
try: try:
ret = self.sqlwrite2.execute( ret = self.sqlwrite2.execute(
"SELECT trans FROM cache WHERE (srclang,tgtlang,source)=(?,?,?)", "SELECT trans FROM cache WHERE (((srclang,tgtlang)=(?,?) or (srclang,tgtlang)=(?,?)) and (source= ?))",
(self.srclang, self.tgtlang, src), (self.srclang_1, self.tgtlang_1, self.srclang, self.tgtlang, src),
).fetchone() ).fetchone()
if ret: if ret:
return ret[0] return ret[0]
@ -213,7 +207,7 @@ class basetrans(commonbase):
self.sqlqueue.put((src, tgt)) self.sqlqueue.put((src, tgt))
def shorttermcacheget(self, src): def shorttermcacheget(self, src):
langkey = (self.srclang, self.tgtlang) langkey = (self.srclang_1, self.tgtlang_1)
if langkey not in self._cache: if langkey not in self._cache:
self._cache[langkey] = {} self._cache[langkey] = {}
try: try:
@ -222,44 +216,38 @@ class basetrans(commonbase):
return None return None
def shorttermcacheset(self, src, tgt): def shorttermcacheset(self, src, tgt):
langkey = (self.srclang, self.tgtlang) langkey = (self.srclang_1, self.tgtlang_1)
if langkey not in self._cache: if langkey not in self._cache:
self._cache[langkey] = {} self._cache[langkey] = {}
self._cache[langkey][src] = tgt self._cache[langkey][src] = tgt
def cached_translate(self, contentsolved, is_auto_run): def shortorlongcacheget(self, content, is_auto_run):
is_using_gpt_and_retrans = is_auto_run == False and self.is_gpt_like if self.is_gpt_like and not is_auto_run:
if is_using_gpt_and_retrans == False: return None
res = self.shorttermcacheget(contentsolved) if self.transtype == "pre":
if res: # 预翻译不使用翻译缓存
return res return None
res = self.shorttermcacheget(content)
if res:
return res
if globalconfig["uselongtermcache"]: if globalconfig["uselongtermcache"]:
res = self.longtermcacheget(contentsolved) return None
if res: res = self.longtermcacheget(content)
return res if res:
return res
return None
if self.transtype == "offline" and not self.is_gpt_like: def maybecachetranslate(self, contentraw, contentsolved, is_auto_run):
# 避免离线gpt被大量翻译阻塞 res = self.shortorlongcacheget(contentraw, is_auto_run)
if res:
return res
if self.transtype in ["offline", "pre", "dev"]:
res = self.translate(contentsolved) res = self.translate(contentsolved)
else: else:
res = self.intervaledtranslate(contentsolved) res = self.intervaledtranslate(contentsolved)
return res return res
def cachesetatend(self, contentsolved, res):
if self.transtype == "pre":
return
if globalconfig["uselongtermcache"]:
self.longtermcacheset(contentsolved, res)
self.shorttermcacheset(contentsolved, res)
def maybecachetranslate(self, contentraw, contentsolved, is_auto_run):
if self.transtype == "pre":
res = self.translate(contentraw)
else:
res = self.cached_translate(contentsolved, is_auto_run)
return res
def intervaledtranslate(self, content): def intervaledtranslate(self, content):
interval = globalconfig["requestinterval"] interval = globalconfig["requestinterval"]
current = time.time() current = time.time()
@ -278,31 +266,6 @@ class basetrans(commonbase):
return res return res
def _iterget(self, __callback, rid, __res):
succ = True
for _res in __res:
if self.requestid != rid:
succ = False
break
__callback(_res, 1)
if succ:
__callback("", 2)
def __callback(self, collectiterres, callback, embedcallback, ares, is_iter_res):
if self.needzhconv:
ares = zhconv.convert(ares, "zh-tw")
if ares == "\0": # 清除前面的输出
collectiterres.clear()
pass
else:
collectiterres.append(ares)
__ = ""
for ares in collectiterres:
if ares is None:
continue
__ += ares
callback(__, embedcallback, is_iter_res)
def reinitandtrans(self, contentraw, contentsolved, is_auto_run): def reinitandtrans(self, contentraw, contentsolved, is_auto_run):
if self.needreinit or self.initok == False: if self.needreinit or self.initok == False:
self.needreinit = False self.needreinit = False
@ -313,11 +276,57 @@ class basetrans(commonbase):
raise Exception("init translator failed : " + str(stringfyerror(e))) raise Exception("init translator failed : " + str(stringfyerror(e)))
return self.maybecachetranslate(contentraw, contentsolved, is_auto_run) return self.maybecachetranslate(contentraw, contentsolved, is_auto_run)
def translate_and_collect(
self,
contentraw,
contentsolved,
is_auto_run,
callback,
):
def __maybeshow(callback, res, is_iter_res):
if self.needzhconv:
res = zhconv.convert(res, "zh-tw")
callback(res, is_iter_res)
callback = functools.partial(__maybeshow, callback)
res = self.reinitandtrans(contentraw, contentsolved, is_auto_run)
# 不能因为被打断而放弃后面的操作,发出的请求不会因为不再处理而无效,所以与其浪费不如存下来
# gettranslationcallback里已经有了是否为当前请求的校验这里无脑输出就行了
if isinstance(res, types.GeneratorType):
collectiterres = ""
for _res in res:
if _res == "\0":
collectiterres = ""
else:
collectiterres += _res
callback(collectiterres, 1)
callback("", 2)
res = collectiterres
else:
if globalconfig["fix_translate_rank"]:
# 这个性能会稍微差一点,不然其实可以全都这样的。
callback(res, 1)
callback("", 2)
else:
callback(res, 0)
# 保存缓存
# 不管是否使用翻译缓存,都存下来
if self.transtype == "pre":
return
self.shorttermcacheset(contentsolved, res)
self.longtermcacheset(contentsolved, res)
def _fythread(self): def _fythread(self):
self.needreinit = False self.needreinit = False
while self.using: while self.using:
content = self.queue.get() content = self.queue.get()
if not self.using:
break
if content is None: if content is None:
break break
# fmt: off # fmt: off
@ -326,76 +335,63 @@ class basetrans(commonbase):
if self.onlymanual and is_auto_run: if self.onlymanual and is_auto_run:
continue continue
if self.using == False:
break
if self.srclang_1 == self.tgtlang_1: if self.srclang_1 == self.tgtlang_1:
callback(contentsolved, embedcallback, False) callback(contentsolved, 0)
continue continue
self.requestid += 1
try: try:
checktutukufunction = ( checktutukufunction = (
lambda: ((embedcallback is not None) or self.queue.empty()) lambda: ((embedcallback is not None) or self.queue.empty())
and self.using and self.using
) )
if checktutukufunction(): if not checktutukufunction():
if self.using_gpt_dict: # 检查请求队列是否空,请求队列有新的请求,则放弃当前请求。但对于内嵌翻译请求,不可以放弃。
gpt_dict = None continue
for _ in optimization_params: if self.using_gpt_dict:
if isinstance(_, dict): gpt_dict = None
_gpt_dict = _.get("gpt_dict", None) for _ in optimization_params:
if _gpt_dict is None: if isinstance(_, dict):
continue _gpt_dict = _.get("gpt_dict", None)
gpt_dict = _gpt_dict if _gpt_dict is None:
continue
gpt_dict = _gpt_dict
contentsolved = json.dumps( contentsolved = json.dumps(
{ {
"text": contentsolved, "text": contentsolved,
"gpt_dict": gpt_dict, "gpt_dict": gpt_dict,
"contentraw": contentraw, "contentraw": contentraw,
} }
)
func = functools.partial(
self.reinitandtrans, contentraw, contentsolved, is_auto_run
) )
res = timeoutfunction(
func = functools.partial(
self.translate_and_collect,
contentraw,
contentsolved,
is_auto_run,
callback,
)
if self.transtype == "offline":
# 离线翻译例如sakura不要被中断因为即使中断了部署的服务仍然在运行直到请求结束
func()
else:
timeoutfunction(
func, func,
checktutukufunction=checktutukufunction, checktutukufunction=checktutukufunction,
) )
collectiterres = []
__callback = functools.partial(
self.__callback, collectiterres, callback, embedcallback
)
if isinstance(res, types.GeneratorType):
timeoutfunction(
functools.partial(
self._iterget, __callback, self.requestid, res
),
checktutukufunction=checktutukufunction,
)
else:
if globalconfig["fix_translate_rank"]:
# 这个性能会稍微差一点,不然其实可以全都这样的。
__callback(res, 1)
__callback("", 2)
else:
__callback(res, 0)
if all([_ is not None for _ in collectiterres]):
self.cachesetatend(contentsolved, "".join(collectiterres))
except Exception as e: except Exception as e:
if self.using and globalconfig["showtranexception"]: if not (self.using and globalconfig["showtranexception"]):
if isinstance(e, ArgsEmptyExc): continue
msg = str(e) if isinstance(e, ArgsEmptyExc):
elif isinstance(e, TimeOut): msg = str(e)
# 更改了timeout机制。timeout只会发生在队列非空时故直接放弃 elif isinstance(e, Interrupted):
continue # 因为有新的请求而被打断
else: continue
print_exc() else:
msg = stringfyerror(e) print_exc()
self.needreinit = True msg = stringfyerror(e)
msg = "<msg_translator>" + msg self.needreinit = True
msg = "<msg_translator>" + msg
callback(msg, embedcallback, False) if embedcallback:
callback(contentraw, 0)
else:
callback(msg, 0)

View File

@ -1133,11 +1133,11 @@
}, },
"prompt_version": { "prompt_version": {
"rank": 1.1, "rank": 1.1,
"name": "prompt格式需要根据模型版本决定。使用v0.10pre1以支持gpt词典", "name": "prompt格式需要根据模型版本决定",
"type": "combo", "type": "combo",
"list": [ "list": [
"v0.9", "v0.9",
"v0.10pre1" "v0.10pre1支持gpt词典"
] ]
}, },
"API接口地址": { "API接口地址": {

View File

@ -28,8 +28,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
include(generate_product_version) include(generate_product_version)
set(VERSION_MAJOR 5) set(VERSION_MAJOR 5)
set(VERSION_MINOR 26) set(VERSION_MINOR 27)
set(VERSION_PATCH 12) set(VERSION_PATCH 0)
add_library(pch pch.cpp) add_library(pch pch.cpp)
target_precompile_headers(pch PUBLIC pch.h) target_precompile_headers(pch PUBLIC pch.h)