diff --git a/docutranslate/agents/agent.py b/docutranslate/agents/agent.py index 6280939..0e016c0 100644 --- a/docutranslate/agents/agent.py +++ b/docutranslate/agents/agent.py @@ -23,8 +23,15 @@ MAX_REQUESTS_PER_ERROR = 15 ThinkingMode = Literal["enable", "disable", "default"] -class PartialTranslationError(ValueError): - """一个特殊的异常,用于表示结果不完整但包含了部分成功的数据,以便触发重试。""" +class AgentResultError(ValueError): + """一个特殊的异常,用于表示结果由AI正常返回,但返回的结果有问题。该错误不计入总错误数""" + + def __init__(self, message): + super().__init__(message) + + +class PartialAgentResultError(ValueError): + """一个特殊的异常,用于表示结果不完整但包含了部分成功的数据,以便触发重试。该错误不计入总错误数""" def __init__(self, message, partial_result: dict): super().__init__(message) @@ -177,9 +184,12 @@ class Agent: # print(f"result:=============================================================\n{result}\n================\n") return result if result_handler is None else result_handler(result, prompt, self.logger) + except AgentResultError as e: + self.logger.error(f"AI返回结果有误: {e}") + should_retry = True # 专门捕获部分翻译错误(软错误) - except PartialTranslationError as e: - self.logger.error(f"收到部分翻译结果,将尝试重试: {e}") + except PartialAgentResultError as e: + self.logger.error(f"收到部分返回结果,将尝试重试: {e}") current_partial_result = e.partial_result should_retry = True # is_hard_error 保持 False @@ -285,7 +295,7 @@ class Agent: headers, data = self._prepare_request_data(prompt, system_prompt) should_retry = False - is_hard_error = False # 新增标志,用于区分是否为硬错误 + is_hard_error = False # 新增标志,用于区分是否为硬错误 current_partial_result = None try: @@ -302,9 +312,11 @@ class Agent: self.logger.info(f"重试成功 (第 {retry_count + 1}/{MAX_RETRY_COUNT + 1} 次尝试)。") return result if result_handler is None else result_handler(result, prompt, self.logger) - + except AgentResultError as e: + self.logger.error(f"AI返回结果有误: {e}") + should_retry = True # 专门捕获部分翻译错误(软错误) - except PartialTranslationError as e: + except PartialAgentResultError as e: self.logger.error(f"收到部分翻译结果,将尝试重试: {e}") current_partial_result = e.partial_result should_retry = True @@ -400,4 +412,4 @@ class Agent: if __name__ == '__main__': - pass \ No newline at end of file + pass diff --git a/docutranslate/agents/glossary_agent.py b/docutranslate/agents/glossary_agent.py index 21c060d..0e40cd4 100644 --- a/docutranslate/agents/glossary_agent.py +++ b/docutranslate/agents/glossary_agent.py @@ -10,6 +10,7 @@ from logging import Logger import json_repair from docutranslate.agents import AgentConfig, Agent +from docutranslate.agents.agent import AgentResultError from docutranslate.utils.json_utils import segments2json_chunks @@ -52,16 +53,16 @@ The output format should be plain JSON text in a list format if result == "": if origin_prompt.strip()!="": logger.error("result为空值但原文不为空") - raise ValueError("result为空值但原文不为空") + raise AgentResultError("result为空值但原文不为空") return [] try: repaired_result = json_repair.loads(result) if not isinstance(repaired_result, list): - raise ValueError(f"GlossaryAgent返回结果不是list的json形式, result: {result}") + raise AgentResultError(f"GlossaryAgent返回结果不是list的json形式, result: {result}") return repaired_result except (RuntimeError, JSONDecodeError) as e: # 将解析错误包装成 ValueError 以便被 send 方法捕获并重试 - raise ValueError(f"结果不能正确解析: {e.__repr__()}") + raise AgentResultError(f"结果不能正确解析: {e.__repr__()}") def _error_result_handler(self, origin_prompt: str, logger: Logger): if origin_prompt == "": diff --git a/docutranslate/agents/segments_agent.py b/docutranslate/agents/segments_agent.py index 992c5dc..349afbb 100644 --- a/docutranslate/agents/segments_agent.py +++ b/docutranslate/agents/segments_agent.py @@ -10,7 +10,7 @@ from logging import Logger from json_repair import json_repair from docutranslate.agents import AgentConfig, Agent -from docutranslate.agents.agent import PartialTranslationError +from docutranslate.agents.agent import PartialAgentResultError, AgentResultError from docutranslate.glossary.glossary import Glossary from docutranslate.utils.json_utils import segments2json_chunks @@ -70,18 +70,17 @@ class SegmentsTranslateAgent(Agent): """ if result == "": if origin_prompt.strip() != "": - logger.error("result为空值但原文不为空") - raise ValueError("result为空值但原文不为空") + raise AgentResultError("result为空值但原文不为空") return {} try: original_chunk = json.loads(origin_prompt) repaired_result = json_repair.loads(result) if not isinstance(repaired_result, dict): - raise ValueError(f"Agent返回结果不是dict的json形式, result: {result}") + raise AgentResultError(f"Agent返回结果不是dict的json形式, result: {result}") if repaired_result == original_chunk: - raise ValueError("翻译结果与原文完全相同,判定为翻译失败,将进行重试。") + raise AgentResultError("翻译结果与原文完全相同,疑似翻译失败,将进行重试。") original_keys = set(original_chunk.keys()) result_keys = set(repaired_result.keys()) @@ -104,7 +103,7 @@ class SegmentsTranslateAgent(Agent): final_chunk[key] = str(original_chunk[key]) # 抛出自定义异常,将部分结果和错误信息一起传递出去 - raise PartialTranslationError("键不匹配,触发重试", partial_result=final_chunk) + raise PartialAgentResultError("键不匹配,触发重试", partial_result=final_chunk) # 如果键完全匹配(理想情况),正常返回 for key, value in repaired_result.items(): @@ -114,7 +113,7 @@ class SegmentsTranslateAgent(Agent): except (RuntimeError, JSONDecodeError) as e: # 对于JSON解析等硬性错误,继续抛出普通ValueError - raise ValueError(f"结果处理失败: {e.__repr__()}") + raise AgentResultError(f"结果处理失败: {e.__repr__()}") def _error_result_handler(self, origin_prompt: str, logger: Logger): """