fix: 修复模型权限正则匹配逻辑及相关缓存清除

- 修复 model_mappings 正则匹配不再受 candidate_models 限制
- Provider 启用/禁用/删除时清除 GlobalModel 解析缓存
- 优先级管理对话框中启用的 Provider 排在禁用的前面
- 修复请求时间线 skipped 状态颜色适配主题
This commit is contained in:
fawney19
2026-01-23 16:10:53 +08:00
parent 3963e424f8
commit 6f597a5f54
6 changed files with 77 additions and 26 deletions

View File

@@ -10,6 +10,7 @@ from sqlalchemy.orm import Session
from src.api.base.admin_adapter import AdminApiAdapter
from src.api.base.models_service import invalidate_models_list_cache
from src.services.cache.model_cache import ModelCacheService
from src.api.base.pipeline import ApiRequestPipeline
from src.core.enums import ProviderBillingType
from src.core.exceptions import InvalidRequestException, NotFoundException
@@ -373,6 +374,11 @@ class AdminUpdateProviderAdapter(AdminApiAdapter):
# 清除 /v1/models 列表缓存is_active 变更会影响模型可用性)
await invalidate_models_list_cache()
# 如果更新了 is_active清除 GlobalModel 解析缓存
# Provider 状态变更会影响模型解析结果
if "is_active" in update_data:
await ModelCacheService.invalidate_all_resolve_cache()
# 如果更新了 billing_type清除缓存
if "billing_type" in update_data:
await ProviderCacheService.invalidate_provider_cache(provider.id)
@@ -421,6 +427,9 @@ class AdminDeleteProviderAdapter(AdminApiAdapter):
# 清除 /v1/models 列表缓存
await invalidate_models_list_cache()
# 清除 GlobalModel 解析缓存(删除 Provider 会影响模型解析结果)
await ModelCacheService.invalidate_all_resolve_cache()
return {"message": "提供商已删除"}

View File

@@ -350,8 +350,8 @@ def check_model_allowed_with_mappings(
匹配优先级:
1. 精确匹配 model_name用户请求的模型名即 GlobalModel.name
2. 精确匹配 candidate_models 中的任一模型名Provider 的 provider_model_mappings
3. 遍历 model_mappings检查每个映射是否匹配 allowed_models 中的任一
2. 精确匹配 candidate_models ∩ allowed_modelsProvider 支持且 Key 允许的模型名
3. 遍历 model_mappings 正则,检查 allowed_models 中是否有匹配
映射匹配顺序说明:
- 按 allowed_models 集合的迭代顺序遍历(通常为字母顺序,因为内部使用 set
@@ -362,8 +362,9 @@ def check_model_allowed_with_mappings(
Args:
model_name: 请求的模型名称GlobalModel.name
allowed_models: 允许的模型配置(来自 Provider Key
model_mappings: GlobalModel 的映射列表(来自 config.model_mappings
candidate_models: 可选的候选模型集合Provider 的 provider_model_names,包含 provider_model_name 和 provider_model_mappings
model_mappings: GlobalModel 的映射列表(来自 config.model_mappings,支持正则表达式
candidate_models: 可选的候选模型集合Provider 的 provider_model_names
仅用于步骤 2 的精确匹配,不影响步骤 3 的正则匹配
Returns:
(is_allowed, matched_model_name):
@@ -400,13 +401,15 @@ def check_model_allowed_with_mappings(
if not model_mappings:
return False, None
# 映射匹配的搜索空间allowed_models ∩ candidate_models
# 只在 Provider 实际支持的模型名中进行正则匹配,避免匹配到 Provider 不支持的模型
if candidate_models is not None:
allowed_set = allowed_set & candidate_models
if len(allowed_set) == 0:
return False, None
# 正则映射匹配:直接在 allowed_models 上进行匹配
# GlobalModel.config.model_mappings 定义了"可以用哪些 Provider 模型名来提供服务"
# 如果 Key 的 allowed_models 中有能被正则匹配的模型名,说明这个 Key 可以用于请求
#
# 注意:不再用 candidate_models 限制搜索空间
# 原因:用户可能只配置了 GlobalModel 的正则映射规则,而没有在 Provider Model 的
# provider_model_mappings 中添加对应的模型名。正则映射的语义是"将请求重定向到匹配的模型名"
# 所以应该直接检查 Key 的 allowed_models 是否包含能被正则匹配的模型名。
#
# 遍历 allowed_set检查是否有模型名能匹配 model_mappings 中的任一正则
# 排序确保确定性行为
for allowed_model in sorted(allowed_set):

View File

@@ -254,6 +254,19 @@ class ModelCacheService:
logger.error(f"GlobalModel resolve 缓存清除失败,可能导致映射不一致: {e}")
logger.debug(f"GlobalModel 缓存已清除: {global_model_id}")
@staticmethod
async def invalidate_all_resolve_cache() -> None:
"""
清除所有 GlobalModel 解析缓存
在 Provider 启用/禁用时调用,因为 Provider 状态变更会影响模型解析结果。
"""
try:
deleted = await CacheService.delete_pattern("global_model:resolve:*")
logger.debug(f"已清除 {deleted} 个 GlobalModel resolve 缓存")
except Exception as e:
logger.error(f"GlobalModel resolve 缓存清除失败: {e}")
@staticmethod
async def resolve_global_model_by_name_or_mapping(
db: Session, model_name: str