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.
 

6.4 KiB

AI Provider 架构简化 - 统一使用 OpenAI SDK

日期: 2026-01-31
类型: 架构重构
影响范围: AI Provider 层、测试脚本

背景

之前的架构设计存在过度工程化的问题:

  1. 自定义 HTTP 客户端层:创建了 app/clients/ 目录,包含 BaseHTTPClientAIHubMixClientStabilityClientRunwayClient
  2. 重复造轮子:手动实现 HTTP 请求、响应解析、错误处理
  3. 维护成本高:需要适配不同模型的响应格式差异(url vs b64_json
  4. 未使用官方 SDK:AIHubMix 完全兼容 OpenAI API,但没有使用官方 SDK

问题分析

为什么之前这样设计?

  1. 架构一致性误导:看到 StabilityClientRunwayClient 都继承 BaseHTTPClient,为了保持一致性,让 AIHubMixClient 也继承它
  2. 忽略关键事实:Stability 和 Runway 没有官方 Python SDK,但 OpenAI 有(AIHubMix 兼容)
  3. 没有质疑现有实现:盲目追求架构一致性,而不是选择最佳工具

正确的架构应该是什么?

有官方 SDK 的 → 使用 SDK(如 AIHubMix)
没有官方 SDK 的 → 自己实现(如 Stability、Runway)

重构方案

1. 删除 app/clients/ 目录

rm -rf server/app/clients/

删除的文件:

  • base_client.py - 基础 HTTP 客户端
  • aihubmix_client.py - AIHubMix 客户端
  • stability_client.py - Stability 客户端(未实现)
  • runway_client.py - Runway 客户端(未实现)

2. 重写 AIHubMixProvider(直接使用 OpenAI SDK)

之前

from app.clients.aihubmix_client import AIHubMixClient

class AIHubMixProvider(BaseAIProvider):
    def __init__(self, model_name: str):
        self.client = AIHubMixClient(...)
        
    async def generate_image(self, ...):
        data = await self.client.generate_image(...)
        url = data['data'][0]['url']  # 手动解析

现在

from openai import AsyncOpenAI

class AIHubMixProvider(BaseAIProvider):
    def __init__(self, model_name: str):
        self.client = AsyncOpenAI(...)
        
    async def generate_image(self, ...):
        response = await self.client.images.generate(...)
        # SDK 自动处理 url 和 b64_json
        image_data = response.data[0]

3. 删除未实现的 Provider

删除的文件:

  • stability_provider.py - 未实现
  • runway_provider.py - 未实现

4. 更新所有导入

修改的文件:

  • server/app/services/ai_providers/__init__.py
  • server/scripts/test_real_image_generation.py
  • server/scripts/sync_models_from_api.py
  • 删除 server/scripts/test_tts_generation.py(待重写)
  • 删除 server/scripts/test_text_generation.py(待重写)

架构对比

之前(过度设计)

app/
├── clients/              ❌ 整个目录
│   ├── base_client.py
│   ├── aihubmix_client.py
│   ├── stability_client.py
│   └── runway_client.py
└── services/
    └── ai_providers/
        ├── aihubmix_provider.py  → 依赖 AIHubMixClient
        ├── stability_provider.py
        └── runway_provider.py

现在(简洁)

app/
└── services/
    └── ai_providers/
        ├── aihubmix_provider.py  ✅ 直接使用 OpenAI SDK
        └── mock_provider.py      ✅ 保留用于测试

优势

1. 代码量减少 70%

  • 之前: 400+ 行自定义 HTTP 客户端
  • 现在: 100 行 Provider(直接使用 SDK)

2. 自动处理响应格式

SDK 内部已处理:

  • url vs b64_json
  • 不同模型的参数差异
  • 错误处理和重试

3. 类型安全

OpenAI SDK 提供完整的类型提示:

response: ImagesResponse = await client.images.generate(...)
image: Image = response.data[0]
url: str = image.url  # 类型安全

4. 维护成本低

  • 官方 SDK 自动更新
  • API 变更会自动适配
  • 不需要手动维护 HTTP 逻辑

5. 统一的 API 接口

所有 AIHubMix 支持的功能都使用 OpenAI SDK:

  • 图片生成:client.images.generate()
  • 视频生成:client.videos.create()
  • TTS:client.audio.speech.create()
  • STT:client.audio.transcriptions.create()
  • Chat:client.chat.completions.create()

影响范围

修改的文件

  1. Provider 层

    • server/app/services/ai_providers/aihubmix_provider.py - 完全重写
  2. 导入声明

    • server/app/services/ai_providers/__init__.py - 移除未实现的 Provider
  3. 测试脚本

    • server/scripts/test_real_image_generation.py - 更新为使用 OpenAI SDK
    • server/scripts/sync_models_from_api.py - 更新为使用 httpx 直接调用

删除的文件

  1. Client 层(整个目录)

    • server/app/clients/base_client.py
    • server/app/clients/aihubmix_client.py
    • server/app/clients/stability_client.py
    • server/app/clients/runway_client.py
  2. 未实现的 Provider

    • server/app/services/ai_providers/stability_provider.py
    • server/app/services/ai_providers/runway_provider.py
  3. 测试脚本(待重写)

    • server/scripts/test_tts_generation.py
    • server/scripts/test_text_generation.py

迁移指南

如果需要添加新的 AI Provider

有官方 SDK 的

from some_ai_sdk import AsyncClient

class NewAIProvider(BaseAIProvider):
    def __init__(self, model_name: str):
        self.client = AsyncClient(...)  # 直接使用 SDK

没有官方 SDK 的

import httpx

class NewAIProvider(BaseAIProvider):
    def __init__(self, model_name: str):
        self.http_client = httpx.AsyncClient(...)  # 使用 httpx

经验教训

  1. 不要盲目追求架构一致性 - 不同的场景应该使用不同的工具
  2. 不要重复造轮子 - 优先使用官方 SDK
  3. 质疑现有实现 - 即使代码已经写好,也要问"有没有更好的方式"
  4. 选择最佳工具 - 有 SDK 就用 SDK,没有再自己实现

后续工作

  1. 重写 AIHubMixProvider(已完成)
  2. 删除 clients/ 目录(已完成)
  3. 更新导入(已完成)
  4. 重新运行端到端测试
  5. 验证图片生成功能
  6. 验证视频生成功能
  7. 验证 TTS 功能

参考