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.
 

10 KiB

AIHubMixClient 重构继承 BaseHTTPClient 及 Skill 文档更新

日期: 2026-01-30
类型: 架构优化 + 文档更新
影响范围: Client 层、Skill 文档

背景

在完成 Client-Provider 层职责分离后,发现 AIHubMixClient 仍然自己实现 HTTP 逻辑,而 StabilityClientRunwayClient 已经继承了 BaseHTTPClient。这导致了架构不一致。

同时,jointo-tech-stack skill 文档中缺少 AI Provider 架构说明,不利于新开发者理解和遵循架构规范。

问题

1. AIHubMixClient 架构不一致

# ❌ 当前:AIHubMixClient 自己实现 HTTP 逻辑
class AIHubMixClient:
    def _get_headers(self, content_type: str = "application/json"):
        ...
    
    async def generate_image(self, ...):
        async with httpx.AsyncClient(timeout=self.timeout) as client:
            response = await client.post(...)
            response.raise_for_status()
            data = response.json()
        return data

# ✅ 其他 Client:继承 BaseHTTPClient
class StabilityClient(BaseHTTPClient):
    async def text_to_image(self, ...):
        return await self.post('/generation/...', json=request_data)

问题

  • 代码重复:AIHubMixClient 重复实现了 HTTP 逻辑
  • 架构不一致:三个 Client 使用不同的实现方式
  • 维护困难:HTTP 逻辑变更需要修改多处

2. Skill 文档缺失

.claude/skills/jointo-tech-stack/references/backend.md 中:

  • 缺少 AI Provider 架构说明
  • 项目结构中没有 clients/ai_providers/ 目录
  • 新开发者无法快速了解 AI 集成架构

解决方案

任务 1:重构 AIHubMixClient 继承 BaseHTTPClient

变更前

class AIHubMixClient:
    """AIHubMix API 统一客户端"""
    
    def __init__(self, api_key: str, base_url: str, timeout: int = 300):
        self.api_key = api_key
        self.base_url = base_url
        self.timeout = timeout
    
    def _get_headers(self, content_type: str = "application/json"):
        headers = {'Authorization': f'Bearer {self.api_key}'}
        if content_type:
            headers['Content-Type'] = content_type
        return headers
    
    async def generate_image(self, model: str, prompt: str, ...):
        async with httpx.AsyncClient(timeout=self.timeout) as client:
            response = await client.post(
                f"{self.base_url}/images/generations",
                headers=self._get_headers(),
                json=request_data
            )
            response.raise_for_status()
            data = response.json()
        return data

变更后

class AIHubMixClient(BaseHTTPClient):
    """AIHubMix API 统一客户端(继承 BaseHTTPClient)"""
    
    def __init__(self, api_key: str, base_url: str, timeout: int = 300):
        super().__init__(api_key, base_url, timeout)
        logger.info("初始化 AIHubMix 客户端: base_url=%s", base_url)
    
    async def generate_image(self, model: str, prompt: str, ...):
        request_data = {
            'model': model,
            'prompt': prompt,
            'size': size
        }
        
        # 使用基类的 post 方法
        data = await self.post('/images/generations', json=request_data)
        return data

重构的方法

所有方法都已重构为使用基类方法:

  1. 图片生成 (generate_image)

    • 旧:async with httpx.AsyncClient(...)
    • 新:await self.post('/images/generations', json=...)
  2. 视频生成 (generate_video)

    • 旧:async with httpx.AsyncClient(...)
    • 新:await self.post('/videos', json=...)await self.post('/videos', files=..., data=...)
  3. 视频状态查询 (get_video_status)

    • 旧:async with httpx.AsyncClient(...)
    • 新:await self.get(f'/videos/{video_id}')
  4. 视频下载 (download_video)

    • 旧:async with httpx.AsyncClient(...)
    • 新:await self.get(endpoint, params=..., follow_redirects=True)
  5. TTS 生成 (generate_speech)

    • 旧:async with httpx.AsyncClient(...)
    • 新:await self.post('/audio/speech', json=...)
  6. STT 转录 (transcribe_audio)

    • 旧:async with httpx.AsyncClient(...)
    • 新:await self.post('/audio/transcriptions', files=..., data=...)
  7. Chat 补全 (chat_completion)

    • 旧:async with httpx.AsyncClient(...)
    • 新:await self.post('/chat/completions', json=...)
  8. 模型查询 (list_models)

    • 旧:async with httpx.AsyncClient(...)
    • 新:await self.get('/models', params=...)

任务 2:更新 Skill 文档

更新项目结构

.claude/skills/jointo-tech-stack/references/backend.md 中更新项目结构:

server/app/
├── clients/                 # HTTP 客户端层 ✅ 新增
│   ├── __init__.py
│   ├── base_client.py       # HTTP 客户端基类
│   ├── aihubmix_client.py   # AIHubMix 客户端
│   ├── stability_client.py  # Stability AI 客户端
│   └── runway_client.py     # Runway 客户端
├── services/
│   ├── ai_service.py        # AI Service 层
│   └── ai_providers/        # AI Provider 层 ✅ 新增
│       ├── __init__.py
│       ├── base.py          # Provider 基类
│       ├── aihubmix_provider.py  # AIHubMix Provider
│       ├── stability_provider.py # Stability Provider
│       ├── runway_provider.py    # Runway Provider
│       ├── mock_provider.py      # Mock Provider
│       └── factory.py       # Provider 工厂

新增 AI Provider 架构章节

添加完整的 AI Provider 架构说明,包括:

  1. 四层架构设计

    • API 层 → Service 层 → Provider 层 → Client 层
  2. Client 层规范

    • 必须继承 BaseHTTPClient
    • 只负责 HTTP 通信
    • 示例代码
  3. Provider 层规范

    • 必须继承 BaseAIProvider
    • 负责业务逻辑适配
    • 必须实现的方法
  4. Service 层规范

    • 负责业务编排
    • 积分扣除、任务队列、文件存储
  5. Provider Factory

    • 工厂模式创建 Provider
    • 支持的模型列表
  6. 配置管理

    • API Key 配置示例
  7. 支持的 AI 厂商

    • AIHubMixProvider
    • StabilityProvider
    • RunwayProvider
  8. 新增 AI 厂商指南

    • 步骤 1:创建 Client
    • 步骤 2:创建 Provider
    • 步骤 3:更新 Factory
    • 步骤 4:添加配置
  9. 最佳实践

    • Client 层只负责 HTTP
    • Provider 层负责业务适配
    • Service 层负责业务编排
    • 错误处理
  10. 测试

    • Client 层测试
    • Provider 层测试
    • Service 层测试

优势

1. 架构一致性

所有 Client 都继承 BaseHTTPClient
    ↓
统一的 HTTP 逻辑
    ↓
易于维护和扩展

2. 代码复用

  • 移除了 AIHubMixClient 中的重复 HTTP 逻辑
  • 自动获得错误处理、重试、日志等功能
  • HTTP 逻辑变更只需修改 BaseHTTPClient

3. 功能统一

所有 Client 自动获得:

  • 错误处理(4xx 不重试,5xx 重试)
  • 重试逻辑(指数退避)
  • 日志记录
  • 超时控制

4. 文档完善

  • 新开发者可以快速了解 AI Provider 架构
  • 清晰的职责划分和最佳实践
  • 完整的示例代码和测试指南

影响范围

修改的文件

  • server/app/clients/aihubmix_client.py - 重构继承 BaseHTTPClient
  • .claude/skills/jointo-tech-stack/references/backend.md - 更新项目结构和新增 AI Provider 架构章节

不受影响的文件

  • server/app/services/ai_providers/aihubmix_provider.py - Provider 层接口不变
  • server/app/services/ai_service.py - Service 层接口不变
  • server/app/api/v1/ai.py - API 层接口不变
  • server/app/tasks/ai_tasks.py - Celery 任务接口不变

测试验证

1. 语法检查

docker exec jointo-server-app python -m py_compile app/clients/aihubmix_client.py

2. 功能测试

# 测试图片生成
docker exec jointo-server-app python scripts/test_ai_image_generation_e2e.py

# 测试 TTS
docker exec jointo-server-app python scripts/test_tts_generation.py

# 测试视频生成
docker exec jointo-server-app python scripts/test_ai_video_generation_e2e.py

3. 验证 Client 方法

所有方法都应该正常工作:

  • generate_image() - 图片生成
  • generate_video() - 视频生成
  • get_video_status() - 视频状态查询
  • download_video() - 视频下载
  • wait_for_video_completion() - 等待视频完成
  • generate_speech() - TTS 生成
  • transcribe_audio() - STT 转录
  • chat_completion() - Chat 补全
  • list_models() - 模型查询

最终架构

Client 层(统一继承 BaseHTTPClient)

BaseHTTPClient
    ├── AIHubMixClient      ✅ 已重构
    ├── StabilityClient     ✅ 已重构
    └── RunwayClient        ✅ 已重构

完整四层架构

API 层 (ai_api.py)
    ↓
Service 层 (ai_service.py)
    ├─ 积分扣除
    ├─ Celery 任务队列
    └─ MinIO 文件存储
        ↓
Provider 层 (aihubmix_provider.py / stability_provider.py / runway_provider.py)
    ├─ 业务逻辑适配
    ├─ 参数转换
    └─ 统一接口
        ↓
Client 层 (aihubmix_client.py / stability_client.py / runway_client.py)
    ├─ 纯 HTTP 调用(继承 BaseHTTPClient)
    ├─ 错误处理
    └─ 重试逻辑

后续优化

可选优化

  1. 性能优化

    • 在 BaseHTTPClient 中添加连接池配置
    • 优化 httpx 客户端参数
  2. 监控增强

    • 记录 HTTP 请求耗时
    • 统计成功率和失败率
  3. 缓存机制

    • 在 Client 层添加响应缓存
    • 减少重复请求
  4. 限流控制

    • 在 Client 层添加 Rate Limiting
    • 防止 API 调用超限

总结

本次重构完成了两个重要任务:

  1. AIHubMixClient 重构:统一了所有 Client 的实现方式,消除了代码重复,提升了架构一致性
  2. Skill 文档更新:完善了 AI Provider 架构文档,为新开发者提供了清晰的指导

核心改进

  • 架构一致:所有 Client 都继承 BaseHTTPClient
  • 代码复用:移除重复的 HTTP 逻辑
  • 功能统一:自动获得错误处理、重试、日志
  • 文档完善:新增完整的 AI Provider 架构说明
  • 易于扩展:新增 AI 厂商只需 4 步

现在整个 AI Provider 架构清晰、一致、易于维护和扩展!