软错误不计入总错误数

This commit is contained in:
xunbu
2025-09-04 16:55:46 +08:00
parent 9c05661496
commit c964eb0da6
3 changed files with 30 additions and 18 deletions

View File

@@ -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
pass

View File

@@ -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 == "":

View File

@@ -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):
"""