From 6f714649a7cb7defedb377217a6260f1396e0392 Mon Sep 17 00:00:00 2001 From: snaily Date: Fri, 25 Jul 2025 17:07:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BB=A5=E7=AC=AC?= =?UTF-8?q?=E4=B8=80=E4=B8=AAkey=E8=8E=B7=E5=8F=96=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=88=97=E8=A1=A8=EF=BC=8C=E5=A6=82=E6=9E=9Ckey=E5=A4=B1?= =?UTF-8?q?=E6=95=88=E5=B0=86=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/router/gemini_routes.py | 2 +- app/router/openai_compatiable_routes.py | 2 +- app/router/openai_routes.py | 2 +- app/router/vertex_express_routes.py | 2 +- app/service/config/config_service.py | 2 +- app/service/key/key_manager.py | 20 ++++++++++++++++++++ 6 files changed, 25 insertions(+), 5 deletions(-) diff --git a/app/router/gemini_routes.py b/app/router/gemini_routes.py index 189c300..8e9d6c6 100644 --- a/app/router/gemini_routes.py +++ b/app/router/gemini_routes.py @@ -50,7 +50,7 @@ async def list_models( logger.info("Handling Gemini models list request") try: - api_key = await key_manager.get_first_valid_key() + api_key = await key_manager.get_random_valid_key() if not api_key: raise HTTPException(status_code=503, detail="No valid API keys available to fetch models.") logger.info(f"Using API key: {redact_key_for_logging(api_key)}") diff --git a/app/router/openai_compatiable_routes.py b/app/router/openai_compatiable_routes.py index 92730d0..958c8ea 100644 --- a/app/router/openai_compatiable_routes.py +++ b/app/router/openai_compatiable_routes.py @@ -46,7 +46,7 @@ async def list_models( operation_name = "list_models" async with handle_route_errors(logger, operation_name): logger.info("Handling models list request") - api_key = await key_manager.get_first_valid_key() + api_key = await key_manager.get_random_valid_key() logger.info(f"Using API key: {redact_key_for_logging(api_key)}") return await openai_service.get_models(api_key) diff --git a/app/router/openai_routes.py b/app/router/openai_routes.py index e6cf9ae..2c590bb 100644 --- a/app/router/openai_routes.py +++ b/app/router/openai_routes.py @@ -60,7 +60,7 @@ async def list_models( operation_name = "list_models" async with handle_route_errors(logger, operation_name): logger.info("Handling models list request") - api_key = await key_manager.get_first_valid_key() + api_key = await key_manager.get_random_valid_key() logger.info(f"Using API key: {redact_key_for_logging(api_key)}") return await model_service.get_gemini_openai_models(api_key) diff --git a/app/router/vertex_express_routes.py b/app/router/vertex_express_routes.py index b4d57c8..1809300 100644 --- a/app/router/vertex_express_routes.py +++ b/app/router/vertex_express_routes.py @@ -46,7 +46,7 @@ async def list_models( logger.info("Handling Gemini models list request") try: - api_key = await key_manager.get_first_valid_key() + api_key = await key_manager.get_random_valid_key() if not api_key: raise HTTPException(status_code=503, detail="No valid API keys available to fetch models.") logger.info(f"Using API key: {redact_key_for_logging(api_key)}") diff --git a/app/service/config/config_service.py b/app/service/config/config_service.py index 10dfa21..64c91c8 100644 --- a/app/service/config/config_service.py +++ b/app/service/config/config_service.py @@ -230,7 +230,7 @@ class ConfigService: key_manager = await get_key_manager_instance() model_service = ModelService() - api_key = await key_manager.get_first_valid_key() + api_key = await key_manager.get_random_valid_key() if not api_key: logger.error("No valid API keys available to fetch model list for UI.") raise HTTPException( diff --git a/app/service/key/key_manager.py b/app/service/key/key_manager.py index efa0d11..d81b6b1 100644 --- a/app/service/key/key_manager.py +++ b/app/service/key/key_manager.py @@ -1,4 +1,5 @@ import asyncio +import random from itertools import cycle from typing import Dict, Union @@ -195,6 +196,25 @@ class KeyManager: return "" return self.api_keys[0] + async def get_random_valid_key(self) -> str: + """获取随机的有效API key""" + valid_keys = [] + async with self.failure_count_lock: + for key in self.key_failure_counts: + if self.key_failure_counts[key] < self.MAX_FAILURES: + valid_keys.append(key) + + if valid_keys: + return random.choice(valid_keys) + + # 如果没有有效的key,返回第一个key作为fallback + if self.api_keys: + logger.warning("No valid keys available, returning first key as fallback.") + return self.api_keys[0] + + logger.warning("API key list is empty, cannot get random valid key.") + return "" + _singleton_instance = None _singleton_lock = asyncio.Lock()