From 88c95db8d0e6518de634700a0b91137a2a9671da Mon Sep 17 00:00:00 2001 From: lanceyq <1982376970@qq.com> Date: Wed, 4 Feb 2026 12:19:00 +0800 Subject: [PATCH 1/4] [add]The main project adds multi-API Key load balancing. --- api/app/controllers/ontology_controller.py | 35 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/api/app/controllers/ontology_controller.py b/api/app/controllers/ontology_controller.py index 43d3b1d2..895b6d40 100644 --- a/api/app/controllers/ontology_controller.py +++ b/api/app/controllers/ontology_controller.py @@ -190,19 +190,48 @@ def _get_ontology_service( detail="指定的LLM模型没有配置API密钥" ) - api_key_config = model_config.api_keys[0] + # 获取可用的 API Key(只选择激活状态的) + active_api_keys = [ak for ak in model_config.api_keys if ak.is_active] + if not active_api_keys: + logger.error(f"Model {llm_id} has no active API key") + raise HTTPException( + status_code=400, + detail="指定的LLM模型没有可用的API密钥" + ) + + # 对于组合模型,根据负载均衡策略选择 API Key + if model_config.is_composite and len(active_api_keys) > 1: + from app.models.models_model import LoadBalanceStrategy + if model_config.load_balance_strategy == LoadBalanceStrategy.ROUND_ROBIN: + # 轮询策略:选择使用次数最少的 API Key + api_key_config = min(active_api_keys, key=lambda x: int(x.usage_count or "0")) + else: + # 默认策略:按优先级选择 + api_key_config = min(active_api_keys, key=lambda x: int(x.priority or "1")) + logger.info( + f"Composite model using load balance strategy: {model_config.load_balance_strategy}, " + f"selected API Key: {api_key_config.id}, provider: {api_key_config.provider}" + ) + else: + api_key_config = active_api_keys[0] logger.info( f"Using specified model - user: {current_user.id}, " - f"model_id: {llm_id}, model_name: {api_key_config.model_name}" + f"model_id: {llm_id}, model_name: {api_key_config.model_name}, " + f"is_composite: {model_config.is_composite}" ) # 创建模型配置对象 from app.core.models.base import RedBearModelConfig + # 对于组合模型,使用 API Key 的 provider;否则使用 model_config 的 provider + actual_provider = api_key_config.provider if model_config.is_composite else ( + model_config.provider if hasattr(model_config, 'provider') else "openai" + ) + llm_model_config = RedBearModelConfig( model_name=api_key_config.model_name, - provider=model_config.provider if hasattr(model_config, 'provider') else "openai", + provider=actual_provider, api_key=api_key_config.api_key, base_url=api_key_config.api_base, max_retries=3, From ffff138a6ff4714e01feec563a23b631d016eec2 Mon Sep 17 00:00:00 2001 From: lanceyq <1982376970@qq.com> Date: Wed, 4 Feb 2026 12:28:05 +0800 Subject: [PATCH 2/4] [changes]Attribute security access, secure numerical conversion, unified use of local variables --- api/app/controllers/ontology_controller.py | 32 +++++++++++++++------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/api/app/controllers/ontology_controller.py b/api/app/controllers/ontology_controller.py index 895b6d40..1c22529b 100644 --- a/api/app/controllers/ontology_controller.py +++ b/api/app/controllers/ontology_controller.py @@ -191,7 +191,7 @@ def _get_ontology_service( ) # 获取可用的 API Key(只选择激活状态的) - active_api_keys = [ak for ak in model_config.api_keys if ak.is_active] + active_api_keys = [ak for ak in model_config.api_keys if getattr(ak, 'is_active', True)] if not active_api_keys: logger.error(f"Model {llm_id} has no active API key") raise HTTPException( @@ -199,17 +199,29 @@ def _get_ontology_service( detail="指定的LLM模型没有可用的API密钥" ) + # 安全的数值转换辅助函数 + def safe_int(value, default: int = 0) -> int: + """安全地将值转换为整数,异常时返回默认值""" + if value is None: + return default + try: + return int(value) + except (ValueError, TypeError): + return default + # 对于组合模型,根据负载均衡策略选择 API Key - if model_config.is_composite and len(active_api_keys) > 1: + is_composite = getattr(model_config, 'is_composite', False) + if is_composite and len(active_api_keys) > 1: from app.models.models_model import LoadBalanceStrategy - if model_config.load_balance_strategy == LoadBalanceStrategy.ROUND_ROBIN: + load_balance_strategy = getattr(model_config, 'load_balance_strategy', None) + if load_balance_strategy == LoadBalanceStrategy.ROUND_ROBIN: # 轮询策略:选择使用次数最少的 API Key - api_key_config = min(active_api_keys, key=lambda x: int(x.usage_count or "0")) + api_key_config = min(active_api_keys, key=lambda x: safe_int(x.usage_count, 0)) else: - # 默认策略:按优先级选择 - api_key_config = min(active_api_keys, key=lambda x: int(x.priority or "1")) + # 默认策略:按优先级选择(优先级数值越小越优先) + api_key_config = min(active_api_keys, key=lambda x: safe_int(x.priority, 1)) logger.info( - f"Composite model using load balance strategy: {model_config.load_balance_strategy}, " + f"Composite model using load balance strategy: {load_balance_strategy}, " f"selected API Key: {api_key_config.id}, provider: {api_key_config.provider}" ) else: @@ -218,15 +230,15 @@ def _get_ontology_service( logger.info( f"Using specified model - user: {current_user.id}, " f"model_id: {llm_id}, model_name: {api_key_config.model_name}, " - f"is_composite: {model_config.is_composite}" + f"is_composite: {is_composite}" ) # 创建模型配置对象 from app.core.models.base import RedBearModelConfig # 对于组合模型,使用 API Key 的 provider;否则使用 model_config 的 provider - actual_provider = api_key_config.provider if model_config.is_composite else ( - model_config.provider if hasattr(model_config, 'provider') else "openai" + actual_provider = api_key_config.provider if is_composite else ( + getattr(model_config, 'provider', None) or "openai" ) llm_model_config = RedBearModelConfig( From 34f0c3b90c06227d9220e322df41a1e7d5b5feb2 Mon Sep 17 00:00:00 2001 From: lanceyq <1982376970@qq.com> Date: Wed, 4 Feb 2026 13:44:07 +0800 Subject: [PATCH 3/4] [changes]Active status filtering logic, API Key selection strategy --- api/app/controllers/ontology_controller.py | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/api/app/controllers/ontology_controller.py b/api/app/controllers/ontology_controller.py index 1c22529b..8ad47bc1 100644 --- a/api/app/controllers/ontology_controller.py +++ b/api/app/controllers/ontology_controller.py @@ -190,15 +190,6 @@ def _get_ontology_service( detail="指定的LLM模型没有配置API密钥" ) - # 获取可用的 API Key(只选择激活状态的) - active_api_keys = [ak for ak in model_config.api_keys if getattr(ak, 'is_active', True)] - if not active_api_keys: - logger.error(f"Model {llm_id} has no active API key") - raise HTTPException( - status_code=400, - detail="指定的LLM模型没有可用的API密钥" - ) - # 安全的数值转换辅助函数 def safe_int(value, default: int = 0) -> int: """安全地将值转换为整数,异常时返回默认值""" @@ -209,9 +200,19 @@ def _get_ontology_service( except (ValueError, TypeError): return default - # 对于组合模型,根据负载均衡策略选择 API Key + # 获取可用的 API Key(只选择激活状态的) + # 注意:is_active 为 None 时视为非激活状态,避免旧记录被错误地当作激活 + active_api_keys = [ak for ak in model_config.api_keys if getattr(ak, 'is_active', None) is True] + if not active_api_keys: + logger.error(f"Model {llm_id} has no active API key") + raise HTTPException( + status_code=400, + detail="指定的LLM模型没有可用的API密钥" + ) + + # 根据负载均衡策略选择 API Key(组合模型和非组合模型统一处理) is_composite = getattr(model_config, 'is_composite', False) - if is_composite and len(active_api_keys) > 1: + if len(active_api_keys) > 1: from app.models.models_model import LoadBalanceStrategy load_balance_strategy = getattr(model_config, 'load_balance_strategy', None) if load_balance_strategy == LoadBalanceStrategy.ROUND_ROBIN: @@ -221,7 +222,7 @@ def _get_ontology_service( # 默认策略:按优先级选择(优先级数值越小越优先) api_key_config = min(active_api_keys, key=lambda x: safe_int(x.priority, 1)) logger.info( - f"Composite model using load balance strategy: {load_balance_strategy}, " + f"Model (is_composite={is_composite}) using load balance strategy: {load_balance_strategy}, " f"selected API Key: {api_key_config.id}, provider: {api_key_config.provider}" ) else: From 333836f5e796cfdca9977fe19c8790bbf5ebc768 Mon Sep 17 00:00:00 2001 From: lanceyq <1982376970@qq.com> Date: Wed, 4 Feb 2026 14:08:09 +0800 Subject: [PATCH 4/4] [changes] --- api/app/controllers/ontology_controller.py | 46 +++------------------- 1 file changed, 6 insertions(+), 40 deletions(-) diff --git a/api/app/controllers/ontology_controller.py b/api/app/controllers/ontology_controller.py index 8ad47bc1..6520d835 100644 --- a/api/app/controllers/ontology_controller.py +++ b/api/app/controllers/ontology_controller.py @@ -182,56 +182,22 @@ def _get_ontology_service( detail=f"找不到指定的LLM模型: {llm_id}" ) - # 验证模型配置了API密钥 - if not model_config.api_keys: - logger.error(f"Model {llm_id} has no API key configuration") - raise HTTPException( - status_code=400, - detail="指定的LLM模型没有配置API密钥" - ) - - # 安全的数值转换辅助函数 - def safe_int(value, default: int = 0) -> int: - """安全地将值转换为整数,异常时返回默认值""" - if value is None: - return default - try: - return int(value) - except (ValueError, TypeError): - return default - - # 获取可用的 API Key(只选择激活状态的) - # 注意:is_active 为 None 时视为非激活状态,避免旧记录被错误地当作激活 - active_api_keys = [ak for ak in model_config.api_keys if getattr(ak, 'is_active', None) is True] - if not active_api_keys: + # 通过 Repository 获取可用的 API Key(负载均衡逻辑由 Repository 处理) + from app.repositories.model_repository import ModelApiKeyRepository + api_keys = ModelApiKeyRepository.get_by_model_config(db, model_config.id) + if not api_keys: logger.error(f"Model {llm_id} has no active API key") raise HTTPException( status_code=400, detail="指定的LLM模型没有可用的API密钥" ) + api_key_config = api_keys[0] - # 根据负载均衡策略选择 API Key(组合模型和非组合模型统一处理) is_composite = getattr(model_config, 'is_composite', False) - if len(active_api_keys) > 1: - from app.models.models_model import LoadBalanceStrategy - load_balance_strategy = getattr(model_config, 'load_balance_strategy', None) - if load_balance_strategy == LoadBalanceStrategy.ROUND_ROBIN: - # 轮询策略:选择使用次数最少的 API Key - api_key_config = min(active_api_keys, key=lambda x: safe_int(x.usage_count, 0)) - else: - # 默认策略:按优先级选择(优先级数值越小越优先) - api_key_config = min(active_api_keys, key=lambda x: safe_int(x.priority, 1)) - logger.info( - f"Model (is_composite={is_composite}) using load balance strategy: {load_balance_strategy}, " - f"selected API Key: {api_key_config.id}, provider: {api_key_config.provider}" - ) - else: - api_key_config = active_api_keys[0] - logger.info( f"Using specified model - user: {current_user.id}, " f"model_id: {llm_id}, model_name: {api_key_config.model_name}, " - f"is_composite: {is_composite}" + f"is_composite: {is_composite}, api_key_id: {api_key_config.id}" ) # 创建模型配置对象