Merge PR #92: feat(keys): trigger immediate model fetch when auto_fetch_models is enabled

This commit is contained in:
fawney19
2026-01-14 21:30:29 +08:00
2 changed files with 63 additions and 0 deletions

View File

@@ -212,6 +212,10 @@ class AdminUpdateEndpointKeyAdapter(AdminApiAdapter):
if not key:
raise NotFoundException(f"Key {self.key_id} 不存在")
# 检查是否开启了 auto_fetch_models用于后续立即获取模型
auto_fetch_enabled_before = key.auto_fetch_models
auto_fetch_enabled_after = self.key_data.auto_fetch_models if "auto_fetch_models" in self.key_data.model_fields_set else auto_fetch_enabled_before
update_data = self.key_data.model_dump(exclude_unset=True)
if "api_key" in update_data:
update_data["api_key"] = crypto_service.encrypt(update_data["api_key"])
@@ -242,6 +246,26 @@ class AdminUpdateEndpointKeyAdapter(AdminApiAdapter):
db.commit()
db.refresh(key)
# 处理 auto_fetch_models 的开启和关闭
if not auto_fetch_enabled_before and auto_fetch_enabled_after:
# 刚刚开启了 auto_fetch_models立即触发一次模型获取
logger.info("[AUTO_FETCH] Key %s 开启自动获取模型,立即触发模型获取", self.key_id)
try:
from src.services.model.fetch_scheduler import get_model_fetch_scheduler
scheduler = get_model_fetch_scheduler()
# 在后台异步执行,不阻塞当前请求
import asyncio
asyncio.create_task(scheduler._fetch_models_for_key_by_id(self.key_id))
except Exception as e:
logger.error(f"触发模型获取失败: {e}")
# 不抛出异常,避免影响 Key 更新操作
elif auto_fetch_enabled_before and not auto_fetch_enabled_after:
# 关闭了 auto_fetch_models将 allowed_models 设置为 null不限制
logger.info("[AUTO_FETCH] Key %s 关闭自动获取模型,清空 allowed_models", self.key_id)
key.allowed_models = None
db.commit()
db.refresh(key)
# 任何字段更新都清除缓存,确保缓存一致性
# 包括 is_active、allowed_models、capabilities 等影响权限和行为的字段
await ProviderCacheService.invalidate_provider_api_key_cache(self.key_id)
@@ -572,4 +596,17 @@ class AdminCreateProviderKeyAdapter(AdminApiAdapter):
f"Formats={self.key_data.api_formats}, Key=***{self.key_data.api_key[-4:]}, ID={new_key.id}"
)
# 如果开启了 auto_fetch_models立即触发一次模型获取
if self.key_data.auto_fetch_models:
logger.info("[AUTO_FETCH] 新 Key %s 开启自动获取模型,立即触发模型获取", new_key.id)
try:
from src.services.model.fetch_scheduler import get_model_fetch_scheduler
scheduler = get_model_fetch_scheduler()
# 在后台异步执行,不阻塞当前请求
import asyncio
asyncio.create_task(scheduler._fetch_models_for_key_by_id(new_key.id))
except Exception as e:
logger.error(f"触发模型获取失败: {e}")
# 不抛出异常,避免影响 Key 创建操作
return _build_key_response(new_key, api_key_plain=self.key_data.api_key)

View File

@@ -764,6 +764,8 @@ class AdminExportConfigAdapter(AdminApiAdapter):
"capabilities": key.capabilities,
"cache_ttl_minutes": key.cache_ttl_minutes,
"max_probe_interval_minutes": key.max_probe_interval_minutes,
"auto_fetch_models": key.auto_fetch_models,
"locked_models": key.locked_models,
"is_active": key.is_active,
}
)
@@ -1123,6 +1125,8 @@ class AdminImportConfigAdapter(AdminApiAdapter):
capabilities=key_data.get("capabilities"),
cache_ttl_minutes=key_data.get("cache_ttl_minutes", 5),
max_probe_interval_minutes=key_data.get("max_probe_interval_minutes", 32),
auto_fetch_models=key_data.get("auto_fetch_models", False),
locked_models=key_data.get("locked_models"),
is_active=key_data.get("is_active", True),
health_by_format={},
circuit_breaker_by_format={},
@@ -1131,6 +1135,12 @@ class AdminImportConfigAdapter(AdminApiAdapter):
existing_key_values.add(plaintext_key)
stats["keys"]["created"] += 1
# 如果开启了 auto_fetch_models记录需要触发获取的 Key ID
if key_data.get("auto_fetch_models", False):
if "keys_to_fetch" not in stats:
stats["keys_to_fetch"] = []
stats["keys_to_fetch"].append(new_key.id)
# 导入 Models
for model_data in prov_data.get("models", []):
global_model_name = model_data.get("global_model_name")
@@ -1238,6 +1248,22 @@ class AdminImportConfigAdapter(AdminApiAdapter):
cache_service = get_cache_invalidation_service()
cache_service.clear_all_caches()
# 触发开启了 auto_fetch_models 的 Key 的模型获取
keys_to_fetch = stats.get("keys_to_fetch", [])
if keys_to_fetch:
logger.info(f"[AUTO_FETCH] 导入了 {len(keys_to_fetch)} 个开启自动获取模型的 Key触发模型获取")
try:
from src.services.model.fetch_scheduler import get_model_fetch_scheduler
import asyncio
scheduler = get_model_fetch_scheduler()
for key_id in keys_to_fetch:
asyncio.create_task(scheduler._fetch_models_for_key_by_id(key_id))
except Exception as e:
logger.error(f"触发模型获取失败: {e}")
# 不影响导入成功的返回
# 从统计信息中移除内部字段
stats.pop("keys_to_fetch", None)
return {
"message": "配置导入成功",
"stats": stats,