api-key为非必填项,且AgentConfig的字段改名为concurrent

This commit is contained in:
xunbu
2025-09-05 17:30:49 +08:00
parent 551344e329
commit c041559c4f
12 changed files with 40 additions and 38 deletions

View File

@@ -42,10 +42,10 @@ class PartialAgentResultError(ValueError):
class AgentConfig: class AgentConfig:
logger: logging.Logger logger: logging.Logger
base_url: str base_url: str
api_key: str api_key: str | None = None
model_id: str model_id: str
temperature: float = 0.7 temperature: float = 0.7
max_concurrent: int = 30 concurrent: int = 30
timeout: int = 2000 timeout: int = 2000
thinking: ThinkingMode = "default" thinking: ThinkingMode = "default"
@@ -114,11 +114,11 @@ class Agent:
if self.baseurl.endswith("/"): if self.baseurl.endswith("/"):
self.baseurl = self.baseurl[:-1] self.baseurl = self.baseurl[:-1]
self.domain = urlparse(self.baseurl).netloc self.domain = urlparse(self.baseurl).netloc
self.key = config.api_key.strip() or "xx" self.key = config.api_key.strip() if config.api_key else "xx"
self.model_id = config.model_id.strip() self.model_id = config.model_id.strip()
self.system_prompt = "" self.system_prompt = ""
self.temperature = config.temperature self.temperature = config.temperature
self.max_concurrent = config.max_concurrent self.max_concurrent = config.concurrent
self.timeout = config.timeout self.timeout = config.timeout
self.thinking = config.thinking self.thinking = config.thinking
self.logger = config.logger or global_logger self.logger = config.logger or global_logger

View File

@@ -233,7 +233,7 @@ class GlossaryAgentConfigPayload(BaseModel):
model_id: str = Field(..., description="用于术语表生成的Agent的模型ID。", examples=["gpt-4-turbo"]) model_id: str = Field(..., description="用于术语表生成的Agent的模型ID。", examples=["gpt-4-turbo"])
to_lang: str = Field(..., description="术语表生成的目标语言。", examples=["简体中文", "English"]) to_lang: str = Field(..., description="术语表生成的目标语言。", examples=["简体中文", "English"])
temperature: float = Field(default=0.7, description="用于术语表生成的Agent的温度参数。") temperature: float = Field(default=0.7, description="用于术语表生成的Agent的温度参数。")
max_concurrent: int = Field(default=30, description="Agent的最大并发请求数。") concurrent: int = Field(default=30, description="Agent的最大并发请求数。")
timeout: int = Field(default=2000, description="Agent的API调用超时时间。") timeout: int = Field(default=2000, description="Agent的API调用超时时间。")
thinking: ThinkingMode = Field(default="default", description="Agent的思考模式。") thinking: ThinkingMode = Field(default="default", description="Agent的思考模式。")
@@ -243,7 +243,7 @@ class BaseWorkflowParams(BaseModel):
skip_translate: bool = Field(default=False, description="是否跳过翻译步骤。如果为True则仅执行文档解析和格式转换。") skip_translate: bool = Field(default=False, description="是否跳过翻译步骤。如果为True则仅执行文档解析和格式转换。")
base_url: Optional[str] = Field(default=None, validation_alias=AliasChoices('base_url', 'baseurl'), description="LLM API的基础URL。当 `skip_translate` 为 `False` 时必填。", base_url: Optional[str] = Field(default=None, validation_alias=AliasChoices('base_url', 'baseurl'), description="LLM API的基础URL。当 `skip_translate` 为 `False` 时必填。",
examples=["https://api.openai.com/v1"]) examples=["https://api.openai.com/v1"])
api_key: Optional[str] = Field(default=None, validation_alias=AliasChoices('api_key', 'key'), description="LLM API的密钥。当 `skip_translate` 为 `False` 时必填", api_key: Optional[str] = Field(default=None, validation_alias=AliasChoices('api_key', 'key'), description="LLM API的密钥(可选)",
examples=["sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxx"]) examples=["sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxx"])
model_id: Optional[str] = Field(default=None, description="要使用的LLM模型ID。当 `skip_translate` 为 `False` 时必填。", model_id: Optional[str] = Field(default=None, description="要使用的LLM模型ID。当 `skip_translate` 为 `False` 时必填。",
examples=["gpt-4o"]) examples=["gpt-4o"])
@@ -251,6 +251,7 @@ class BaseWorkflowParams(BaseModel):
chunk_size: int = Field(default=default_params["chunk_size"], description="文本分割的块大小(字符)。") chunk_size: int = Field(default=default_params["chunk_size"], description="文本分割的块大小(字符)。")
concurrent: int = Field(default=default_params["concurrent"], description="并发请求数。") concurrent: int = Field(default=default_params["concurrent"], description="并发请求数。")
temperature: float = Field(default=default_params["temperature"], description="LLM温度参数。") temperature: float = Field(default=default_params["temperature"], description="LLM温度参数。")
timeout: int = Field(default=2000, description="API调用超时时间毫秒")
thinking: ThinkingMode = Field(default=default_params["thinking"], description="Agent的思考模式。", thinking: ThinkingMode = Field(default=default_params["thinking"], description="Agent的思考模式。",
examples=["default", "enable", "disable"]) examples=["default", "enable", "disable"])
custom_prompt: Optional[str] = Field(None, description="用户自定义的翻译Prompt。", alias="custom_prompt") custom_prompt: Optional[str] = Field(None, description="用户自定义的翻译Prompt。", alias="custom_prompt")
@@ -267,8 +268,6 @@ class BaseWorkflowParams(BaseModel):
# Check for standard keys or their aliases # Check for standard keys or their aliases
if not (values.get('base_url') or values.get('baseurl')): if not (values.get('base_url') or values.get('baseurl')):
raise ValueError("当 `skip_translate` 为 `False` 时, `base_url` 或 `baseurl` 字段是必须的。") raise ValueError("当 `skip_translate` 为 `False` 时, `base_url` 或 `baseurl` 字段是必须的。")
if not (values.get('api_key') or values.get('key')):
raise ValueError("当 `skip_translate` 为 `False` 时, `api_key` 或 `key` 字段是必须的。")
if not values.get('model_id'): if not values.get('model_id'):
raise ValueError("当 `skip_translate` 为 `False` 时, `model_id` 字段是必须的。") raise ValueError("当 `skip_translate` 为 `False` 时, `model_id` 字段是必须的。")
# 如果跳过翻译,则不进行任何检查,允许 base_url 等字段为空 # 如果跳过翻译,则不进行任何检查,允许 base_url 等字段为空
@@ -417,6 +416,7 @@ class TranslateServiceRequest(BaseModel):
"chunk_size": default_params["chunk_size"], "chunk_size": default_params["chunk_size"],
"concurrent": default_params["concurrent"], "concurrent": default_params["concurrent"],
"temperature": default_params["temperature"], "temperature": default_params["temperature"],
"timeout": 2000,
"thinking": "default", "thinking": "default",
"glossary_generate_enable": False, "glossary_generate_enable": False,
"convert_engine": "mineru", "convert_engine": "mineru",
@@ -438,6 +438,7 @@ class TranslateServiceRequest(BaseModel):
"chunk_size": default_params["chunk_size"], "chunk_size": default_params["chunk_size"],
"concurrent": default_params["concurrent"], "concurrent": default_params["concurrent"],
"temperature": default_params["temperature"], "temperature": default_params["temperature"],
"timeout": 2000,
"thinking": "default", "thinking": "default",
"glossary_generate_enable": False, "glossary_generate_enable": False,
"json_paths": ["$.product.name", "$.product.description", "$.features[*]"], "json_paths": ["$.product.name", "$.product.description", "$.features[*]"],
@@ -456,6 +457,7 @@ class TranslateServiceRequest(BaseModel):
"chunk_size": default_params["chunk_size"], "chunk_size": default_params["chunk_size"],
"concurrent": default_params["concurrent"], "concurrent": default_params["concurrent"],
"temperature": default_params["temperature"], "temperature": default_params["temperature"],
"timeout": 2000,
"thinking": "default", "thinking": "default",
"glossary_generate_enable": False, "glossary_generate_enable": False,
"insert_mode": "replace", "insert_mode": "replace",
@@ -483,7 +485,7 @@ class TranslateServiceRequest(BaseModel):
"model_id": "gpt-4-turbo", "model_id": "gpt-4-turbo",
"to_lang": "中文", "to_lang": "中文",
"temperature": 0.7, "temperature": 0.7,
"max_concurrent": 30, "concurrent": 30,
"timeout": 2000, "timeout": 2000,
"thinking": "default" "thinking": "default"
} }
@@ -504,6 +506,7 @@ class TranslateServiceRequest(BaseModel):
"chunk_size": default_params["chunk_size"], "chunk_size": default_params["chunk_size"],
"concurrent": default_params["concurrent"], "concurrent": default_params["concurrent"],
"temperature": default_params["temperature"], "temperature": default_params["temperature"],
"timeout": 2000,
"thinking": "default", "thinking": "default",
} }
}, },
@@ -522,6 +525,7 @@ class TranslateServiceRequest(BaseModel):
"chunk_size": default_params["chunk_size"], "chunk_size": default_params["chunk_size"],
"concurrent": default_params["concurrent"], "concurrent": default_params["concurrent"],
"temperature": default_params["temperature"], "temperature": default_params["temperature"],
"timeout": 2000,
"thinking": "default", "thinking": "default",
} }
}, },
@@ -540,6 +544,7 @@ class TranslateServiceRequest(BaseModel):
"chunk_size": default_params["chunk_size"], "chunk_size": default_params["chunk_size"],
"concurrent": default_params["concurrent"], "concurrent": default_params["concurrent"],
"temperature": default_params["temperature"], "temperature": default_params["temperature"],
"timeout": 2000,
"thinking": "default", "thinking": "default",
} }
}, },
@@ -558,6 +563,7 @@ class TranslateServiceRequest(BaseModel):
"chunk_size": default_params["chunk_size"], "chunk_size": default_params["chunk_size"],
"concurrent": default_params["concurrent"], "concurrent": default_params["concurrent"],
"temperature": default_params["temperature"], "temperature": default_params["temperature"],
"timeout": 2000,
"thinking": "default", "thinking": "default",
} }
} }
@@ -612,7 +618,7 @@ async def _perform_translation(
task_logger.info("构建 MarkdownBasedWorkflow 配置。") task_logger.info("构建 MarkdownBasedWorkflow 配置。")
translator_args = payload.model_dump(include={ translator_args = payload.model_dump(include={
'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt', 'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt',
'temperature', 'thinking', 'chunk_size', 'concurrent', 'glossary_dict' 'temperature', 'thinking', 'chunk_size', 'concurrent', 'glossary_dict', 'timeout'
}, exclude_none=True) }, exclude_none=True)
translator_args['glossary_generate_enable'] = payload.glossary_generate_enable translator_args['glossary_generate_enable'] = payload.glossary_generate_enable
translator_args['glossary_agent_config'] = build_glossary_agent_config() translator_args['glossary_agent_config'] = build_glossary_agent_config()
@@ -639,7 +645,7 @@ async def _perform_translation(
translator_args = payload.model_dump(include={ translator_args = payload.model_dump(include={
'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt', 'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt',
'temperature', 'thinking', 'chunk_size', 'concurrent', 'glossary_dict', 'temperature', 'thinking', 'chunk_size', 'concurrent', 'glossary_dict',
'insert_mode', 'separator' 'insert_mode', 'separator', 'timeout'
}, exclude_none=True) }, exclude_none=True)
translator_args['glossary_generate_enable'] = payload.glossary_generate_enable translator_args['glossary_generate_enable'] = payload.glossary_generate_enable
translator_args['glossary_agent_config'] = build_glossary_agent_config() translator_args['glossary_agent_config'] = build_glossary_agent_config()
@@ -657,7 +663,7 @@ async def _perform_translation(
translator_args = payload.model_dump(include={ translator_args = payload.model_dump(include={
'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt', 'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt',
'temperature', 'thinking', 'chunk_size', 'concurrent', 'glossary_dict', 'temperature', 'thinking', 'chunk_size', 'concurrent', 'glossary_dict',
'json_paths' 'json_paths', 'timeout'
}, exclude_none=True) }, exclude_none=True)
translator_args['glossary_generate_enable'] = payload.glossary_generate_enable translator_args['glossary_generate_enable'] = payload.glossary_generate_enable
translator_args['glossary_agent_config'] = build_glossary_agent_config() translator_args['glossary_agent_config'] = build_glossary_agent_config()
@@ -675,7 +681,7 @@ async def _perform_translation(
translator_args = payload.model_dump(include={ translator_args = payload.model_dump(include={
'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt', 'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt',
'temperature', 'thinking', 'chunk_size', 'concurrent', 'temperature', 'thinking', 'chunk_size', 'concurrent',
'insert_mode', 'separator', 'translate_regions', 'glossary_dict' 'insert_mode', 'separator', 'translate_regions', 'glossary_dict', 'timeout'
}, exclude_none=True) }, exclude_none=True)
translator_args['glossary_generate_enable'] = payload.glossary_generate_enable translator_args['glossary_generate_enable'] = payload.glossary_generate_enable
translator_args['glossary_agent_config'] = build_glossary_agent_config() translator_args['glossary_agent_config'] = build_glossary_agent_config()
@@ -694,7 +700,7 @@ async def _perform_translation(
translator_args = payload.model_dump(include={ translator_args = payload.model_dump(include={
'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt', 'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt',
'temperature', 'thinking', 'chunk_size', 'concurrent', 'temperature', 'thinking', 'chunk_size', 'concurrent',
'insert_mode', 'separator', 'glossary_dict' 'insert_mode', 'separator', 'glossary_dict', 'timeout'
}, exclude_none=True) }, exclude_none=True)
translator_args['glossary_generate_enable'] = payload.glossary_generate_enable translator_args['glossary_generate_enable'] = payload.glossary_generate_enable
translator_args['glossary_agent_config'] = build_glossary_agent_config() translator_args['glossary_agent_config'] = build_glossary_agent_config()
@@ -713,7 +719,7 @@ async def _perform_translation(
translator_args = payload.model_dump(include={ translator_args = payload.model_dump(include={
'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt', 'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt',
'temperature', 'thinking', 'chunk_size', 'concurrent', 'temperature', 'thinking', 'chunk_size', 'concurrent',
'insert_mode', 'separator', 'glossary_dict' 'insert_mode', 'separator', 'glossary_dict', 'timeout'
}, exclude_none=True) }, exclude_none=True)
translator_args['glossary_generate_enable'] = payload.glossary_generate_enable translator_args['glossary_generate_enable'] = payload.glossary_generate_enable
translator_args['glossary_agent_config'] = build_glossary_agent_config() translator_args['glossary_agent_config'] = build_glossary_agent_config()
@@ -732,7 +738,7 @@ async def _perform_translation(
translator_args = payload.model_dump(include={ translator_args = payload.model_dump(include={
'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt', 'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt',
'temperature', 'thinking', 'chunk_size', 'concurrent', 'temperature', 'thinking', 'chunk_size', 'concurrent',
'insert_mode', 'separator', 'glossary_dict' 'insert_mode', 'separator', 'glossary_dict', 'timeout'
}, exclude_none=True) }, exclude_none=True)
translator_args['glossary_generate_enable'] = payload.glossary_generate_enable translator_args['glossary_generate_enable'] = payload.glossary_generate_enable
translator_args['glossary_agent_config'] = build_glossary_agent_config() translator_args['glossary_agent_config'] = build_glossary_agent_config()
@@ -752,7 +758,7 @@ async def _perform_translation(
translator_args = payload.model_dump(include={ translator_args = payload.model_dump(include={
'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt', 'skip_translate', 'base_url', 'api_key', 'model_id', 'to_lang', 'custom_prompt',
'temperature', 'thinking', 'chunk_size', 'concurrent', 'temperature', 'thinking', 'chunk_size', 'concurrent',
'insert_mode', 'separator', 'glossary_dict' 'insert_mode', 'separator', 'glossary_dict', 'timeout'
}, exclude_none=True) }, exclude_none=True)
translator_args['glossary_generate_enable'] = payload.glossary_generate_enable translator_args['glossary_generate_enable'] = payload.glossary_generate_enable
translator_args['glossary_agent_config'] = build_glossary_agent_config() translator_args['glossary_agent_config'] = build_glossary_agent_config()

File diff suppressed because one or more lines are too long

View File

@@ -4,28 +4,24 @@ from abc import abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import TypeVar from typing import TypeVar
from docutranslate.agents.agent import ThinkingMode from docutranslate.agents.agent import ThinkingMode, AgentConfig
from docutranslate.agents.glossary_agent import GlossaryAgentConfig, GlossaryAgent from docutranslate.agents.glossary_agent import GlossaryAgentConfig, GlossaryAgent
from docutranslate.ir.document import Document from docutranslate.ir.document import Document
from docutranslate.translator.base import Translator, TranslatorConfig from docutranslate.translator.base import Translator, TranslatorConfig
@dataclass(kw_only=True) @dataclass(kw_only=True)
class AiTranslatorConfig(TranslatorConfig): class AiTranslatorConfig(TranslatorConfig, AgentConfig):
base_url: str | None = field(default=None,metadata={"description": "OpenAI兼容地址当skip_translate为False时为必填项"}) base_url: str | None = field(default=None,
api_key: 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时为必填项"}) 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
temperature: float = 0.7
thinking: ThinkingMode = "default"
timeout: int = 2000
chunk_size: int = 3000 chunk_size: int = 3000
concurrent: int = 30
glossary_dict: dict[str:str] | None = field(default=None) glossary_dict: dict[str:str] | None = field(default=None)
glossary_generate_enable: bool = False glossary_generate_enable: bool = False
glossary_agent_config: GlossaryAgentConfig | None = None glossary_agent_config: GlossaryAgentConfig | None = None
skip_translate: bool = False skip_translate: bool = False # 当skip_translate为False时base_url、model_id为必填项
T = TypeVar('T', bound=Document) T = TypeVar('T', bound=Document)
@@ -55,7 +51,7 @@ class AiTranslator(Translator[T]):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
) )

View File

@@ -49,7 +49,7 @@ class DocxTranslator(AiTranslator):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
glossary_dict=config.glossary_dict glossary_dict=config.glossary_dict

View File

@@ -40,7 +40,7 @@ class EpubTranslator(AiTranslator):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
glossary_dict=config.glossary_dict glossary_dict=config.glossary_dict

View File

@@ -97,7 +97,7 @@ class HtmlTranslator(AiTranslator):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
glossary_dict=config.glossary_dict glossary_dict=config.glossary_dict

View File

@@ -30,7 +30,7 @@ class JsonTranslator(AiTranslator):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
glossary_dict=config.glossary_dict glossary_dict=config.glossary_dict

View File

@@ -30,7 +30,7 @@ class MDTranslator(AiTranslator):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
glossary_dict=config.glossary_dict) glossary_dict=config.glossary_dict)

View File

@@ -36,7 +36,7 @@ class SrtTranslator(AiTranslator):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
glossary_dict=config.glossary_dict glossary_dict=config.glossary_dict

View File

@@ -54,7 +54,7 @@ class TXTTranslator(AiTranslator):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
glossary_dict=config.glossary_dict glossary_dict=config.glossary_dict

View File

@@ -38,7 +38,7 @@ class XlsxTranslator(AiTranslator):
model_id=config.model_id, model_id=config.model_id,
temperature=config.temperature, temperature=config.temperature,
thinking=config.thinking, thinking=config.thinking,
max_concurrent=config.concurrent, concurrent=config.concurrent,
timeout=config.timeout, timeout=config.timeout,
logger=self.logger, logger=self.logger,
glossary_dict=config.glossary_dict glossary_dict=config.glossary_dict