You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

4.4 KiB

AI Provider Factory 数据库驱动重构

日期: 2026-02-10
类型: 重构
影响范围: AI Provider 选择逻辑

背景

之前的 AIProviderFactory 使用硬编码的模型列表(ELEVENLABS_MODELSAIHUBMIX_MODELS)来判断使用哪个 Provider,存在以下问题:

  1. 数据冗余:模型信息既在数据库 ai_models 表中,又在代码中硬编码
  2. 维护困难:新增模型需要同时修改数据库和代码
  3. 不一致风险:数据库中的模型可能与代码中的列表不同步
  4. 灵活性差:无法动态启用/禁用模型,必须修改代码

解决方案

采用启动时缓存方案:

  • 应用启动时从数据库加载所有活跃模型到内存缓存
  • create_provider() 方法从缓存查询模型的 provider 字段
  • 根据 provider 动态选择对应的 Provider 实例
  • 提供 refresh_cache() 方法支持运行时刷新缓存

变更内容

1. 修改 AIProviderFactory (server/app/services/ai_providers/factory.py)

新增:

  • _provider_cache: Dict[str, int] - 内存缓存,存储 {model_name: provider}
  • initialize(db) - 应用启动时初始化缓存
  • refresh_cache(db) - 运行时刷新缓存
  • get_cached_provider(model_name) - 从缓存获取 Provider ID

修改:

  • create_provider() - 从缓存查询 Provider,而非硬编码列表
  • 根据 AIProvider 枚举值动态选择 Provider 实例

移除:

  • ELEVENLABS_MODELS - 硬编码的 ElevenLabs 模型列表
  • AIHUBMIX_MODELS - 硬编码的 AIHubMix 模型列表

2. 修改 main.py (server/app/main.py)

lifespan() 函数中添加 AI Provider Factory 初始化逻辑:

# 初始化 AI Provider Factory 缓存
try:
    from app.core.database import get_db
    from app.services.ai_providers.factory import AIProviderFactory
    
    async for db in get_db():
        await AIProviderFactory.initialize(db)
        logger.info("✅ AI Provider Factory initialized")
        break
except Exception as e:
    logger.error(f"❌ Failed to initialize AI Provider Factory: {e}")
    # 不抛出异常,允许应用继续运行(降级到 Mock Provider)

优势

  1. 单一数据源:模型配置完全由数据库管理
  2. 动态配置:通过数据库启用/禁用模型,无需修改代码
  3. 高性能:启动时加载到内存,运行时无需查询数据库
  4. 易维护:新增模型只需在数据库中添加记录
  5. 可扩展:支持运行时刷新缓存(通过 refresh_cache() 方法)

降级策略

  • 如果缓存初始化失败,应用仍可正常启动
  • 未在缓存中的模型会自动降级到 MockAIProvider
  • 保留 use_mock 配置选项,支持强制使用 Mock Provider

后续优化

可选的后续改进:

  1. 缓存刷新 API:添加管理员 API 端点,支持手动刷新缓存
  2. 缓存预热:在模型同步脚本执行后自动刷新缓存 已实现
  3. 缓存监控:添加缓存命中率监控和日志

自动刷新机制

已实现:模型同步脚本自动刷新缓存

sync_models_from_api.py 执行完成后,会自动调用 AIProviderFactory.refresh_cache() 刷新缓存:

# 刷新 AI Provider Factory 缓存
try:
    from app.services.ai_providers.factory import AIProviderFactory
    await AIProviderFactory.refresh_cache(session)
    logger.info("✅ AI Provider Factory 缓存已刷新")
except Exception as e:
    logger.warning("刷新 AI Provider Factory 缓存失败: %s", str(e))
    # 不影响同步结果

使用方式:

# 同步模型(自动刷新缓存)
docker exec jointo-server-app python scripts/sync_models_from_api.py

# 输出示例:
# ============================================================
# 同步完成
#    新增: 5
#    更新: 0
#    跳过: 16
# ============================================================
# ✅ AI Provider Factory 缓存已刷新

测试建议

  1. 启动应用,检查日志中的缓存初始化信息
  2. 验证不同 Provider 的模型是否正确创建
  3. 测试未激活模型是否正确降级到 Mock Provider
  4. 测试数据库不可用时的降级行为

相关文件

  • server/app/services/ai_providers/factory.py - AI Provider Factory
  • server/app/main.py - 应用入口
  • server/app/repositories/ai_model_repository.py - AI Model Repository
  • server/app/models/ai_model.py - AI Model 数据模型