前后端增加system_proxy_enable选项

This commit is contained in:
xunbu committed 2025-09-24 10:37:42 +08:00
1 parent f611468a13
commit ac6fcebe24
5 files changed
+989 -388

No files matched your search

+5 -4
View File
@@ -250,6 +250,7 @@ class Agent:
self.retry = config.retry self.retry = config.retry
self.system_proxy_enable = config.system_proxy_enable self.system_proxy_enable = config.system_proxy_enable
def _add_thinking_mode(self, data: dict): def _add_thinking_mode(self, data: dict):
if self.domain not in self._think_factory: if self.domain not in self._think_factory:
return return
@@ -445,7 +446,7 @@ class Agent:
) )
total = len(prompts) total = len(prompts)
self.logger.info( self.logger.info(
f"base-url:{self.baseurl},model-id:{self.model_id},concurrent:{max_concurrent},temperature:{self.temperature}" f"base-url:{self.baseurl},model-id:{self.model_id},concurrent:{max_concurrent},temperature:{self.temperature},system_proxy:{self.system_proxy_enable}"
) )
self.logger.info(f"预计发送{total}个请求,并发请求数:{max_concurrent}") self.logger.info(f"预计发送{total}个请求,并发请求数:{max_concurrent}")
self.total_error_counter.max_errors_count = ( self.total_error_counter.max_errors_count = (
@@ -500,7 +501,7 @@ class Agent:
# 新增:打印token使用统计 # 新增:打印token使用统计
token_stats = self.token_counter.get_stats() token_stats = self.token_counter.get_stats()
if token_stats['input_tokens'] < 0: if token_stats["input_tokens"] < 0:
self.logger.info("Token统计失败") self.logger.info("Token统计失败")
else: else:
self.logger.info( self.logger.info(
@@ -687,7 +688,7 @@ class Agent:
error_result_handler: ErrorResultHandlerType = None, error_result_handler: ErrorResultHandlerType = None,
) -> list[Any]: ) -> list[Any]:
self.logger.info( self.logger.info(
f"base-url:{self.baseurl},model-id:{self.model_id},concurrent:{self.max_concurrent},temperature:{self.temperature}" f"base-url:{self.baseurl},model-id:{self.model_id},concurrent:{self.max_concurrent},temperature:{self.temperature},system_proxy:{self.system_proxy_enable}"
) )
self.logger.info( self.logger.info(
f"预计发送{len(prompts)}个请求,并发请求数:{self.max_concurrent}" f"预计发送{len(prompts)}个请求,并发请求数:{self.max_concurrent}"
@@ -737,7 +738,7 @@ class Agent:
# 新增:打印token使用统计 # 新增:打印token使用统计
token_stats = self.token_counter.get_stats() token_stats = self.token_counter.get_stats()
if token_stats['input_tokens'] < 0: if token_stats["input_tokens"] < 0:
self.logger.info("Token统计失败") self.logger.info("Token统计失败")
else: else:
self.logger.info( self.logger.info(
+962 -372
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1 +1 @@
<!DOCTYPE html> <html lang="zh-CN" data-bs-theme="auto"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title data-i18n-title="pageTitle">DocuTranslate - 交互式文档翻译</title> <link rel="icon" href="/static/favicon.ico" type="image/x-icon"> <!-- Bootstrap CSS --> <link href="/static/bootstrap.css" rel="stylesheet" crossorigin="anonymous"> <!-- Bootstrap Icons --> <link rel="stylesheet" href="/static/bootstrap-icons.css"> <style> body { background-color: var(--bs-body-bg); } button:focus { outline: none !important; box-shadow: none !important; } .main-container { display: flex; flex-direction: column; height: 100vh; padding-top: 1rem; padding-bottom: 1rem; } .settings-panel { height: calc(100vh - 2rem); overflow-y: auto; padding-right: 15px; /* for scrollbar */ } .task-area { height: calc(100vh - 2rem); overflow-y: auto; } .task-card { transition: all 0.3s ease-in-out; } .task-id-placeholder { color: var(--bs-secondary-color); font-style: italic; } .log-area { height: 150px; background-color: var(--bs-tertiary-bg); border: 1px solid var(--bs-border-color); border-radius: .375rem; font-family: monospace; font-size: 0.8rem; padding: 10px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; } .file-drop-area { border: 2px dashed var(--bs-secondary-bg); border-radius: .375rem; padding: 2rem; text-align: center; cursor: pointer; transition: all 0.2s ease-in-out; background-color: var(--bs-body-bg); } .file-drop-area.drag-over { border-color: var(--bs-primary); background-color: var(--bs-secondary-bg); } .file-drop-area.file-selected { border-style: solid; border-color: var(--bs-success); background-color: var(--bs-success-bg-subtle); } .file-drop-area.input-error { border-color: var(--bs-danger); } .file-name-display.input-error-text { color: var(--bs-danger); font-weight: bold; } #printFrame, #translatedPreviewFrame { border: none; width: 100%; } #previewOffcanvas { --bs-offcanvas-width: 95vw; max-width: 1600px; } .preview-split-container { display: flex; flex-direction: row; height: 90%; } .preview-pane-wrapper { display: flex; flex-direction: column; overflow: hidden; /* Important for split.js */ } .preview-pane-wrapper h6 { flex-shrink: 0; padding: 0.25rem; } .preview-pane-wrapper .preview-pane { flex-grow: 1; /* Make the inner pane grow */ border: 1px solid var(--bs-border-color); border-radius: .375rem; overflow: auto; } .gutter { background-color: var(--bs-tertiary-bg); background-repeat: no-repeat; background-position: 50%; } .gutter.gutter-horizontal { cursor: col-resize; border-left: 1px solid var(--bs-border-color); border-right: 1px solid var(--bs-border-color); } .gutter.gutter-vertical { cursor: row-resize; border-top: 1px solid var(--bs-border-color); border-bottom: 1px solid var(--bs-border-color); } .preview-pane iframe, .preview-pane pre { width: 100%; height: 95%; border: none; margin: 0; padding: 0; overflow: auto; background-color: var(--bs-body-bg); } .slider-reset-btn { visibility: hidden; } .bottom-left-controls { position: fixed; bottom: 1rem; left: 1rem; z-index: 1050; display: flex; gap: 0.5rem; } .project-info p { letter-spacing: 0.8px; line-height: 1.6; } @media (max-width: 991.98px) { .main-container { height: auto; padding-bottom: 6rem; } .settings-panel, .task-area { height: auto; overflow-y: visible; } .settings-panel { pLine truncated <!DOCTYPE html> <html lang="zh-CN" data-bs-theme="auto"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title data-i18n-title="pageTitle">DocuTranslate - 交互式文档翻译</title> <link rel="icon" href="/static/favicon.ico" type="image/x-icon"> <!-- Bootstrap CSS --> <link href="/static/bootstrap.css" rel="stylesheet" crossorigin="anonymous"> <!-- Bootstrap Icons --> <link rel="stylesheet" href="/static/bootstrap-icons.css"> <style> body { background-color: var(--bs-body-bg); } button:focus { outline: none !important; box-shadow: none !important; } .main-container { display: flex; flex-direction: column; height: 100vh; padding-top: 1rem; padding-bottom: 1rem; } .settings-panel { height: calc(100vh - 2rem); overflow-y: auto; padding-right: 15px; /* for scrollbar */ } .task-area { height: calc(100vh - 2rem); overflow-y: auto; } .task-card { transition: all 0.3s ease-in-out; } .task-id-placeholder { color: var(--bs-secondary-color); font-style: italic; } .log-area { height: 150px; background-color: var(--bs-tertiary-bg); border: 1px solid var(--bs-border-color); border-radius: .375rem; font-family: monospace; font-size: 0.8rem; padding: 10px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; } .file-drop-area { border: 2px dashed var(--bs-secondary-bg); border-radius: .375rem; padding: 2rem; text-align: center; cursor: pointer; transition: all 0.2s ease-in-out; background-color: var(--bs-body-bg); } .file-drop-area.drag-over { border-color: var(--bs-primary); background-color: var(--bs-secondary-bg); } .file-drop-area.file-selected { border-style: solid; border-color: var(--bs-success); background-color: var(--bs-success-bg-subtle); } .file-drop-area.input-error { border-color: var(--bs-danger); } .file-name-display.input-error-text { color: var(--bs-danger); font-weight: bold; } #printFrame, #translatedPreviewFrame { border: none; width: 100%; } #previewOffcanvas { --bs-offcanvas-width: 95vw; max-width: 1600px; } .preview-split-container { display: flex; flex-direction: row; height: 90%; } .preview-pane-wrapper { display: flex; flex-direction: column; overflow: hidden; /* Important for split.js */ } .preview-pane-wrapper h6 { flex-shrink: 0; padding: 0.25rem; } .preview-pane-wrapper .preview-pane { flex-grow: 1; /* Make the inner pane grow */ border: 1px solid var(--bs-border-color); border-radius: .375rem; overflow: auto; } .gutter { background-color: var(--bs-tertiary-bg); background-repeat: no-repeat; background-position: 50%; } .gutter.gutter-horizontal { cursor: col-resize; border-left: 1px solid var(--bs-border-color); border-right: 1px solid var(--bs-border-color); } .gutter.gutter-vertical { cursor: row-resize; border-top: 1px solid var(--bs-border-color); border-bottom: 1px solid var(--bs-border-color); } .preview-pane iframe, .preview-pane pre { width: 100%; height: 95%; border: none; margin: 0; padding: 0; overflow: auto; background-color: var(--bs-body-bg); } .slider-reset-btn { visibility: hidden; } .bottom-left-controls { position: fixed; bottom: 1rem; left: 1rem; z-index: 1050; display: flex; gap: 0.5rem; } .project-info p { letter-spacing: 0.8px; line-height: 1.6; } @media (max-width: 991.98px) { .main-container { height: auto; padding-bottom: 6rem; } .settings-panel, .task-area { height: auto; overflow-y: visible; } .settings-panel { pLine truncated
+18 -11
View File
@@ -12,9 +12,13 @@ from docutranslate.translator.base import Translator, TranslatorConfig
@dataclass(kw_only=True) @dataclass(kw_only=True)
class AiTranslatorConfig(TranslatorConfig, AgentConfig): class AiTranslatorConfig(TranslatorConfig, AgentConfig):
base_url: str | None = field(default=None, base_url: str | None = field(
metadata={"description": "OpenAI兼容地址,当skip_translate为False时为必填项"}) default=None,
model_id: str | None = field(default=None, metadata={"description": "当skip_translate为False时为必填项"}) metadata={"description": "OpenAI兼容地址,当skip_translate为False时为必填项"},
)
model_id: str | None = field(
default=None, metadata={"description": "当skip_translate为False时为必填项"}
)
to_lang: str = "简体中文" to_lang: str = "简体中文"
custom_prompt: str | None = None custom_prompt: str | None = None
chunk_size: int = 3000 chunk_size: int = 3000
@@ -24,7 +28,7 @@ class AiTranslatorConfig(TranslatorConfig, AgentConfig):
skip_translate: bool = False # 当skip_translate为False时base_url、model_id为必填项 skip_translate: bool = False # 当skip_translate为False时base_url、model_id为必填项
T = TypeVar('T', bound=Document) T = TypeVar("T", bound=Document)
class AiTranslator(Translator[T]): class AiTranslator(Translator[T]):
@@ -37,8 +41,12 @@ class AiTranslator(Translator[T]):
self.skip_translate = config.skip_translate self.skip_translate = config.skip_translate
self.glossary_agent = None self.glossary_agent = None
self.glossary_dict_gen = None self.glossary_dict_gen = None
if not self.skip_translate and (config.base_url is None or config.api_key is None or config.model_id is None): if not self.skip_translate and (
raise ValueError("skip_translate不为false时,base_url、api_key、model_id为必填项") config.base_url is None or config.api_key is None or config.model_id is None
):
raise ValueError(
"skip_translate不为false时,base_url、api_key、model_id为必填项"
)
if config.glossary_generate_enable: if config.glossary_generate_enable:
if config.glossary_agent_config: if config.glossary_agent_config:
@@ -54,14 +62,13 @@ class AiTranslator(Translator[T]):
concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
retry=config.retry retry=config.retry,
system_proxy_enable=config.system_proxy_enable,
) )
self.glossary_agent = GlossaryAgent(glossary_agent_config) self.glossary_agent = GlossaryAgent(glossary_agent_config)
@abstractmethod @abstractmethod
def translate(self, document: T) -> Document: def translate(self, document: T) -> Document: ...
...
@abstractmethod @abstractmethod
async def translate_async(self, document: T) -> Document: async def translate_async(self, document: T) -> Document: ...
...
+3
View File
@@ -12,3 +12,6 @@ def get_httpx_proxies():
if http_proxy: if http_proxy:
proxies["http://"] = http_proxy proxies["http://"] = http_proxy
return proxies return proxies
if __name__ == '__main__':
print(get_httpx_proxies())