Spaces:
Paused
Paused
Upload app.py
Browse files
app.py
CHANGED
|
@@ -273,7 +273,7 @@ class AuthManager:
|
|
| 273 |
return ""
|
| 274 |
|
| 275 |
def _get_headers(self, with_content_type: bool = False) -> Dict[str, str]:
|
| 276 |
-
"""
|
| 277 |
headers = {
|
| 278 |
'apikey': self._fetch_apikey(),
|
| 279 |
'user-agent': _USER_AGENT
|
|
@@ -309,53 +309,48 @@ class MultiAuthManager:
|
|
| 309 |
self.current_index = 0
|
| 310 |
self._last_rotation = time.time()
|
| 311 |
self._rotation_interval = 300 # 5分钟轮转间隔
|
| 312 |
-
self.
|
| 313 |
-
self.
|
| 314 |
-
|
| 315 |
-
def _should_rotate(self) -> bool:
|
| 316 |
-
"""检查是否应该轮转到下一个账号"""
|
| 317 |
-
current_date = datetime.now().date()
|
| 318 |
-
# 如果是新的一天且上一个成功的账号失败了,才进行完整轮询
|
| 319 |
-
return current_date > self._last_success_date
|
| 320 |
|
| 321 |
def get_next_auth_manager(self, model):
|
| 322 |
-
"""
|
| 323 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 324 |
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
while True:
|
| 336 |
-
auth_manager = self.auth_managers[current_index]
|
| 337 |
-
if auth_manager.is_model_available(model) and auth_manager._should_attempt_auth():
|
| 338 |
-
self._last_successful_index = current_index
|
| 339 |
-
return auth_manager
|
| 340 |
-
|
| 341 |
-
current_index = (current_index + 1) % len(self.auth_managers)
|
| 342 |
-
if current_index == start_index:
|
| 343 |
-
break
|
| 344 |
-
|
| 345 |
return None
|
| 346 |
|
| 347 |
-
def
|
| 348 |
-
"""
|
| 349 |
for i, manager in enumerate(self.auth_managers):
|
| 350 |
if manager._email == auth_manager._email:
|
| 351 |
-
self.
|
| 352 |
-
self._last_success_date = datetime.now().date()
|
| 353 |
break
|
| 354 |
|
| 355 |
def ensure_valid_token(self, model):
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
|
|
|
| 359 |
return None
|
| 360 |
|
| 361 |
def reset_all_model_status(self):
|
|
@@ -800,7 +795,7 @@ def build_payload(request_data, model_id):
|
|
| 800 |
return payload
|
| 801 |
|
| 802 |
def make_request(payload, auth_manager, model_id):
|
| 803 |
-
"""
|
| 804 |
global multi_auth_manager
|
| 805 |
max_retries = 3
|
| 806 |
retry_delay = 1
|
|
@@ -826,6 +821,9 @@ def make_request(payload, auth_manager, model_id):
|
|
| 826 |
while len(tried_accounts) < len(multi_auth_manager.auth_managers):
|
| 827 |
auth_manager = multi_auth_manager.get_next_auth_manager(model_id)
|
| 828 |
if not auth_manager:
|
|
|
|
|
|
|
|
|
|
| 829 |
break
|
| 830 |
|
| 831 |
# 如果这个账号已经尝试过,继续下一个
|
|
@@ -849,8 +847,7 @@ def make_request(payload, auth_manager, model_id):
|
|
| 849 |
|
| 850 |
if response.status_code == 200 and response.headers.get('Content-Type') == 'text/event-stream':
|
| 851 |
logger.info(f"请求成功,使用账号 {auth_manager._email}")
|
| 852 |
-
#
|
| 853 |
-
multi_auth_manager.update_last_success(auth_manager)
|
| 854 |
return response
|
| 855 |
|
| 856 |
headers_cache.clear()
|
|
@@ -886,41 +883,43 @@ def make_request(payload, auth_manager, model_id):
|
|
| 886 |
raise Exception("所有账号均不可用,且注册新账号失败")
|
| 887 |
|
| 888 |
def health_check():
|
| 889 |
-
"""
|
| 890 |
-
check_index = 0
|
|
|
|
|
|
|
| 891 |
|
| 892 |
while True:
|
| 893 |
try:
|
| 894 |
-
if multi_auth_manager
|
| 895 |
current_time = time.time()
|
| 896 |
-
|
| 897 |
-
|
| 898 |
-
# 获取当前要检查的账号
|
| 899 |
-
auth_manager = multi_auth_manager.auth_managers[check_index]
|
| 900 |
-
email = auth_manager._email
|
| 901 |
-
|
| 902 |
-
# 检查当前账号
|
| 903 |
-
if auth_manager._should_attempt_auth():
|
| 904 |
-
if not auth_manager.ensure_valid_token():
|
| 905 |
-
logger.warning(f"Auth token validation failed during health check for {email}")
|
| 906 |
-
auth_manager.clear_auth()
|
| 907 |
-
else:
|
| 908 |
-
logger.info(f"Health check passed for {email}")
|
| 909 |
-
else:
|
| 910 |
-
logger.info(f"Skipping health check for {email} due to rate limiting")
|
| 911 |
-
|
| 912 |
-
# 更新索引,准备下一次检查下一个账号
|
| 913 |
-
check_index = (check_index + 1) % len(multi_auth_manager.auth_managers)
|
| 914 |
|
| 915 |
-
#
|
| 916 |
-
if
|
|
|
|
| 917 |
multi_auth_manager.reset_all_model_status()
|
| 918 |
-
logger.info("Reset model status for all accounts")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 919 |
|
| 920 |
except Exception as e:
|
| 921 |
logger.error(f"Health check error: {e}")
|
| 922 |
|
| 923 |
-
sleep(
|
| 924 |
|
| 925 |
# 为了兼容 Flask CLI 和 Gunicorn,修改启动逻辑
|
| 926 |
if __name__ != "__main__":
|
|
|
|
| 273 |
return ""
|
| 274 |
|
| 275 |
def _get_headers(self, with_content_type: bool = False) -> Dict[str, str]:
|
| 276 |
+
"""生成请求头。"""
|
| 277 |
headers = {
|
| 278 |
'apikey': self._fetch_apikey(),
|
| 279 |
'user-agent': _USER_AGENT
|
|
|
|
| 309 |
self.current_index = 0
|
| 310 |
self._last_rotation = time.time()
|
| 311 |
self._rotation_interval = 300 # 5分钟轮转间隔
|
| 312 |
+
self.last_successful_index = 0 # 新增:记录上一次成功的账号索引
|
| 313 |
+
self.daily_rotation_triggered = False # 新增:标记是否触发过每日轮询
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
|
| 315 |
def get_next_auth_manager(self, model):
|
| 316 |
+
"""改进的账号选择逻辑,从上一次成功的账号开始"""
|
| 317 |
+
# 如果当前账号可用,直接返回
|
| 318 |
+
current_auth = self.auth_managers[self.last_successful_index]
|
| 319 |
+
if current_auth.is_model_available(model) and current_auth._should_attempt_auth():
|
| 320 |
+
return current_auth
|
| 321 |
+
|
| 322 |
+
# 如果当前账号不可用,且未触发每日轮询,则等待到第二天
|
| 323 |
+
if not self.daily_rotation_triggered:
|
| 324 |
+
return None
|
| 325 |
+
|
| 326 |
+
# 进行账号轮询
|
| 327 |
+
start_index = (self.last_successful_index + 1) % len(self.auth_managers)
|
| 328 |
+
current_index = start_index
|
| 329 |
|
| 330 |
+
while True:
|
| 331 |
+
auth_manager = self.auth_managers[current_index]
|
| 332 |
+
if auth_manager.is_model_available(model) and auth_manager._should_attempt_auth():
|
| 333 |
+
self.last_successful_index = current_index
|
| 334 |
+
return auth_manager
|
| 335 |
+
|
| 336 |
+
current_index = (current_index + 1) % len(self.auth_managers)
|
| 337 |
+
if current_index == start_index:
|
| 338 |
+
break
|
| 339 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 340 |
return None
|
| 341 |
|
| 342 |
+
def set_successful_account(self, auth_manager):
|
| 343 |
+
"""记录成功使用的账号索引"""
|
| 344 |
for i, manager in enumerate(self.auth_managers):
|
| 345 |
if manager._email == auth_manager._email:
|
| 346 |
+
self.last_successful_index = i
|
|
|
|
| 347 |
break
|
| 348 |
|
| 349 |
def ensure_valid_token(self, model):
|
| 350 |
+
for _ in range(len(self.auth_managers)):
|
| 351 |
+
auth_manager = self.get_next_auth_manager(model)
|
| 352 |
+
if auth_manager and auth_manager.ensure_valid_token():
|
| 353 |
+
return auth_manager
|
| 354 |
return None
|
| 355 |
|
| 356 |
def reset_all_model_status(self):
|
|
|
|
| 795 |
return payload
|
| 796 |
|
| 797 |
def make_request(payload, auth_manager, model_id):
|
| 798 |
+
"""发送请求并处理可能的认证刷新和模型特定错误。"""
|
| 799 |
global multi_auth_manager
|
| 800 |
max_retries = 3
|
| 801 |
retry_delay = 1
|
|
|
|
| 821 |
while len(tried_accounts) < len(multi_auth_manager.auth_managers):
|
| 822 |
auth_manager = multi_auth_manager.get_next_auth_manager(model_id)
|
| 823 |
if not auth_manager:
|
| 824 |
+
if not multi_auth_manager.daily_rotation_triggered:
|
| 825 |
+
logger.info("当前账号不可用,等待至次日重试")
|
| 826 |
+
raise Exception("当前账号不可用,请等待至次日重试")
|
| 827 |
break
|
| 828 |
|
| 829 |
# 如果这个账号已经尝试过,继续下一个
|
|
|
|
| 847 |
|
| 848 |
if response.status_code == 200 and response.headers.get('Content-Type') == 'text/event-stream':
|
| 849 |
logger.info(f"请求成功,使用账号 {auth_manager._email}")
|
| 850 |
+
multi_auth_manager.set_successful_account(auth_manager) # 记录成功的账号
|
|
|
|
| 851 |
return response
|
| 852 |
|
| 853 |
headers_cache.clear()
|
|
|
|
| 883 |
raise Exception("所有账号均不可用,且注册新账号失败")
|
| 884 |
|
| 885 |
def health_check():
|
| 886 |
+
"""改进的健康检查函数,每次只检查一个账号"""
|
| 887 |
+
check_index = 0
|
| 888 |
+
last_check_time = time.time()
|
| 889 |
+
last_date = datetime.now().date()
|
| 890 |
|
| 891 |
while True:
|
| 892 |
try:
|
| 893 |
+
if multi_auth_manager:
|
| 894 |
current_time = time.time()
|
| 895 |
+
current_date = datetime.now().date()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 896 |
|
| 897 |
+
# 检查是否是新的一天
|
| 898 |
+
if current_date > last_date:
|
| 899 |
+
multi_auth_manager.daily_rotation_triggered = True
|
| 900 |
multi_auth_manager.reset_all_model_status()
|
| 901 |
+
logger.info("New day started - Reset model status for all accounts")
|
| 902 |
+
last_date = current_date
|
| 903 |
+
|
| 904 |
+
# 每60秒检查一个账号
|
| 905 |
+
if current_time - last_check_time >= 60:
|
| 906 |
+
auth_manager = multi_auth_manager.auth_managers[check_index]
|
| 907 |
+
|
| 908 |
+
if auth_manager._should_attempt_auth():
|
| 909 |
+
if not auth_manager.ensure_valid_token():
|
| 910 |
+
logger.warning(f"Auth token validation failed during health check for {auth_manager._email}")
|
| 911 |
+
auth_manager.clear_auth()
|
| 912 |
+
else:
|
| 913 |
+
logger.info(f"Health check passed for {auth_manager._email}")
|
| 914 |
+
|
| 915 |
+
# 更新检查索引和时间
|
| 916 |
+
check_index = (check_index + 1) % len(multi_auth_manager.auth_managers)
|
| 917 |
+
last_check_time = current_time
|
| 918 |
|
| 919 |
except Exception as e:
|
| 920 |
logger.error(f"Health check error: {e}")
|
| 921 |
|
| 922 |
+
sleep(1) # 降低CPU使用率
|
| 923 |
|
| 924 |
# 为了兼容 Flask CLI 和 Gunicorn,修改启动逻辑
|
| 925 |
if __name__ != "__main__":
|