mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-05-30 20:59:45 +08:00
- 将 `_build_payload`、`_build_tools`、`_get_safety_settings` 和 `_has_image_parts` 函数从 `OpenAIChatService` 和 `GeminiChatService` 类中提取为独立的函数。 - 将 `_handle_stream_response` 和 `_handle_normal_response` 函数从 `GeminiResponseHandler` 和 `OpenAIResponseHandler` 类中提取为独立的函数。 - 将 `_extract_text` 函数从 `OpenAIResponseHandler` 类中提取为独立的函数, 并在 `GeminiResponseHandler` 中复用。 - 将 `_convert_image` 函数从 `OpenAIMessageConverter` 类中提取为独立的函数。 - 优化 `OpenAIChatService` 和 `GeminiChatService` 中的代码结构, 使其更清晰。 - 优化 `app/api/openai_routes.py` 和 `app/api/gemini_routes.py` 中的路由函数, 移除不必要的参数。
42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
# app/services/chat/retry_handler.py
|
|
|
|
from typing import TypeVar, Callable
|
|
from functools import wraps
|
|
from app.core.logger import get_retry_logger
|
|
from app.services.key_manager import KeyManager
|
|
|
|
T = TypeVar('T')
|
|
logger = get_retry_logger()
|
|
|
|
|
|
class RetryHandler:
|
|
"""重试处理装饰器"""
|
|
|
|
def __init__(self, max_retries: int = 3, key_manager: KeyManager = None, key_arg: str = "api_key"):
|
|
self.max_retries = max_retries
|
|
self.key_manager = key_manager
|
|
self.key_arg = key_arg
|
|
|
|
def __call__(self, func: Callable[..., T]) -> Callable[..., T]:
|
|
@wraps(func)
|
|
async def wrapper(*args, **kwargs) -> T:
|
|
last_exception = None
|
|
|
|
for attempt in range(self.max_retries):
|
|
try:
|
|
return await func(*args, **kwargs)
|
|
except Exception as e:
|
|
last_exception = e
|
|
logger.warning(f"API call failed with error: {str(e)}. Attempt {attempt + 1} of {self.max_retries}")
|
|
|
|
if self.key_manager:
|
|
old_key = kwargs.get(self.key_arg)
|
|
new_key = await self.key_manager.handle_api_failure(old_key)
|
|
kwargs[self.key_arg] = new_key
|
|
logger.info(f"Switched to new API key: {new_key}")
|
|
|
|
logger.error(f"All retry attempts failed, raising final exception: {str(last_exception)}")
|
|
raise last_exception
|
|
|
|
return wrapper
|