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.
 

15 KiB

Changelog: AI 对话生成参数分离

日期: 2026-02-13
版本: v1.0
类型: 架构优化 (架构改进)
影响范围: ai_conversations API + Service


📋 概述

将对话 AI 生成接口 /{conversation_id}/generate 的参数从单一 params 字典拆分为:

  • aiParams: AI 模型参数(独立对象)
  • businessParams: 业务参数(独立对象,可选)

这使得参数职责更清晰,易于验证和扩展。


🎯 改动目标

问题背景

原有的 params 字段混合了两类参数:

{
  "params": {
    "modelId": "dall-e-3",
    "resolution": "1024",         // AI 参数
    "aspectRatio": "1:1",         // AI 参数
    "outputFormat": "png",        // AI 参数
    "saveToProject": true,        // 业务参数
    "autoPublish": false          // 业务参数
  }
}

问题

  1. 职责不清:AI 参数和业务参数混在一起
  2. 扩展困难:新增业务参数可能与 AI 参数命名冲突
  3. 验证复杂:无法分别验证 AI 参数和业务参数

改进方案

采用嵌套结构,将参数分为三层:

{
  "messageId": "xxx",
  "generationType": "image",
  "modelId": "dall-e-3",         //  模型 ID(顶层字段)
  "aiParams": {                   //  AI 模型参数(独立对象)
    "resolution": "1024",
    "aspectRatio": "1:1",
    "outputFormat": "png",
    "seed": 42
  },
  "businessParams": {             //  业务参数(通用字典,可选)
    "customField1": "value1",
    "customField2": true
  }
}

说明

  • businessParams通用字典Dict[str, Any]),字段由业务需求决定
  • 当前仅记录日志,等业务需求明确后再实现具体逻辑

🛠️ 技术实现

1. 新增 Schema 定义

文件: server/app/schemas/ai_conversation.py

1.1 AI 模型参数 Schema
class AIGenerationParams(BaseModel):
    """AI 生成参数(模型参数)"""
    model_config = ConfigDict(populate_by_name=True)
    
    # 简单模式参数
    resolution: Optional[str] = None
    aspect_ratio: Optional[str] = Field(None, alias="aspectRatio")
    quality: Optional[str] = None
    
    # 高级模式参数
    width: Optional[int] = None
    height: Optional[int] = None
    duration: Optional[int] = None
    fps: Optional[int] = None
    
    # 高级参数 - 输出控制
    output_format: Optional[str] = Field(None, alias="outputFormat")
    num_images: Optional[int] = Field(None, alias="numImages")
    
    # 高级参数 - 控制参数
    seed: Optional[int] = None
    watermark: Optional[bool] = None
    
    # 参考图片
    reference_images: Optional[list[str]] = Field(None, alias="referenceImages")
    
    # Wan 视频模式
    video_mode: Optional[str] = Field(None, alias="videoMode")

说明

  • 包含所有 AI 模型相关参数
  • 支持简单模式(resolution, aspectRatio)和高级模式(width, height, seed
  • 与 RFC 144 的统一参数协议保持一致
1.2 业务参数 Schema
class GenerateRequest(BaseModel):
    """触发 AI 生成请求
    
    参数分层:
    - modelId: 模型 ID(顶层字段)
    - aiParams: AI 模型参数(独立对象)
    - businessParams: 业务参数(通用字典,可选,字段待业务需求明确)
    """
    model_config = ConfigDict(populate_by_name=True)
    
    message_id: UUID = Field(..., alias="messageId", description="消息 ID(用于关联)")
    generation_type: str = Field(..., alias="generationType", description="生成类型(image/video)")
    model_id: str = Field(..., alias="modelId", description="模型 ID")
    
    # AI 模型参数(独立对象)
    ai_params: AIGenerationParams = Field(..., alias="aiParams", description="AI 模型参数")
    
    # 业务参数(通用字典,可选,待业务需求明确)
    business_params: Optional[Dict[str, Any]] = Field(
        None, 
        alias="businessParams", 
        description="业务参数(保存、发布、通知等,字段待定义)"
    )

说明

  • businessParamsOptional[Dict[str, Any]](通用字典)
  • 不预先定义具体字段,由业务需求决定
  • 当前仅记录日志,后续根据需求实现具体功能

示例字段(未来可能使用):

{
  "businessParams": {
    "saveToProject": true,       // 是否保存到项目
    "autoPublish": false,        // 是否自动发布
    "tagIds": ["tag1", "tag2"],  // 关联标签
    "createVersion": false,      // 是否创建版本
    "notifyOnComplete": true     // 完成时通知
  }
}

2. Service 层改动

文件: server/app/services/ai_conversation_service.py

2.1 更新 trigger_ai_generation 方法签名

async def trigger_ai_generation(
    self,
    conversation_id: UUID,
    user_id: UUID,
    message_id: UUID,
    generation_type: str,
    model_id: str,                           # ✅ 新增:从参数提升到方法参数
    ai_params: Dict[str, Any],               # ✅ 新增:AI 模型参数(独立)
    business_params: Optional[Dict[str, Any]] = None  # ✅ 新增:业务参数(独立)
) -> Dict[str, Any]:

变化

  • 原有单一 params 拆分为 model_id, ai_params, business_params
  • business_params 为可选参数(默认 None

2.2 更新参数处理逻辑

图片生成 (Image Generation)
if generation_type == 'image':
    prompt = message.content
    
    # 使用 ParamMapper 转换 AI 参数
    from app.utils.param_mapper import ParamMapper
    generate_params = ParamMapper.convert_image_params(ai_params)
    
    # 添加参考图片
    if reference_images:
        generate_params['reference_images'] = reference_images
    
    # 处理业务参数(如果提供,当前仅记录日志)
    if business_params:
        logger.info("收到业务参数(待实现): %s", business_params)
        # TODO: 等业务需求明确后,实现具体逻辑
    
    # 调用生成图片方法
    result = await ai_service.generate_image(
        user_id=str(user_id),
        prompt=prompt,
        model=model_id,
        project_id=str(conversation.project_id) if conversation.project_id else None,
        **generate_params
    )
视频生成 (Video Generation)
elif generation_type == 'video':
    video_type = ai_params.get('videoType', 'text2video')
    prompt = message.content
    
    # 使用 ParamMapper 转换 AI 参数
    from app.utils.param_mapper import ParamMapper
    generate_params = ParamMapper.convert_video_params(ai_params)
    
    # 处理业务参数(如果提供,当前仅记录日志)
    if business_params:
        logger.info("收到业务参数(待实现): %s", business_params)
    
    # 调用生成视频方法
    result = await ai_service.generate_video(
        user_id=str(user_id),
        video_type=video_type,
        prompt=prompt,
        image_url=image_url,
        model=model_id,
        project_id=str(conversation.project_id) if conversation.project_id else None,
        **generate_params
    )

3. API Router 改动

文件: server/app/api/v1/ai_conversations.py

@router.post("/{conversation_id}/generate", response_model=SuccessResponse[TriggerAIGenerationResponse], summary="触发 AI 生成")
async def trigger_generation(
    conversation_id: UUID,
    request: GenerateRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """从对话触发 AI 生成任务
    
    参数分层(RFC 144 扩展):
    - **modelId**: 模型 ID(顶层字段)
    - **aiParams**: AI 模型参数(resolution, aspectRatio, seed 等)
    - **businessParams**: 业务参数(通用字典,可选,字段待业务需求明确)
    
    示例请求 1(仅 AI 参数):
    ```json
    {
      "messageId": "xxx",
      "generationType": "image",
      "modelId": "dall-e-3",
      "aiParams": {
        "resolution": "1024",
        "aspectRatio": "1:1"
      }
    }
    ```
    
    示例请求 2(AI + 业务参数):
    ```json
    {
      "messageId": "xxx",
      "generationType": "image",
      "modelId": "dall-e-3",
      "aiParams": {
        "resolution": "1024",
        "aspectRatio": "1:1"
      },
      "businessParams": {
        "customField1": "value1"
      }
    }
    ```
    """
    service = AIConversationService(db)
    
    # 将 Pydantic 对象转换为字典
    ai_params_dict = request.ai_params.model_dump(by_alias=False, exclude_none=True)
    business_params_dict = request.business_params  # 已经是 Dict 或 None
    
    result = await service.trigger_ai_generation(
        conversation_id=conversation_id,
        user_id=current_user.user_id,
        message_id=request.message_id,
        generation_type=request.generation_type,
        model_id=request.model_id,
        ai_params=ai_params_dict,
        business_params=business_params_dict
    )
    # 返回结果(略)

关键变化

  1. 使用 .model_dump()aiParams Pydantic 对象转换为字典
  2. businessParamsDictNone,直接传递
  3. 分别传递 model_id, ai_params, business_params 给 Service

📊 对比总结

请求格式对比

Before (旧格式)

{
  "messageId": "xxx",
  "generationType": "image",
  "params": {
    "modelId": "dall-e-3",          //  混合在一起
    "resolution": "1024",           //  AI 参数
    "aspectRatio": "1:1",           //  AI 参数
    "saveToProject": true           //  业务参数
  }
}

After (新格式)

{
  "messageId": "xxx",
  "generationType": "image",
  "modelId": "dall-e-3",            //  提升为顶级字段
  "aiParams": {                      //  AI 参数(独立对象)
    "resolution": "1024",
    "aspectRatio": "1:1",
    "outputFormat": "png",
    "seed": 42
  },
  "businessParams": {                //  业务参数(通用字典,可选)
    "customField1": "value1",
    "customField2": true
  }
}

🎯 改进效果

1. 职责清晰

  • AI 参数:只包含模型相关参数(resolution, seed 等)
  • 业务参数:只包含业务逻辑参数(saveToProject, autoPublish 等)
  • modelId:提升为顶级字段,明确模型选择

2. 易于验证

# AI 参数验证
ai_params = AIGenerationParams(**request.aiParams)  # Pydantic 验证

# 业务参数验证(通用字典,由业务逻辑决定)
business_params = request.businessParams  # Dict[str, Any] 或 None

3. 易于扩展

  • 新增 AI 参数:只需修改 AIGenerationParams
  • 新增业务参数:直接在 businessParams 字典中添加字段,无需修改 Schema
  • 无命名冲突:两类参数完全隔离

4. 灵活的业务参数

# 业务参数为通用字典(可选)
business_params: Optional[Dict[str, Any]] = None

# 字段由业务需求决定
{
  "businessParams": {
    "saveToProject": true,      // 未来可能使用
    "autoPublish": false,       // 未来可能使用
    "customField": "value"      // 灵活扩展
  }
}

🧪 验证测试

测试场景

1. 纯 AI 参数请求(无业务参数)

curl -X POST http://localhost:8000/api/v1/ai-conversations/{id}/generate \
  -H "Authorization: Bearer xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "messageId": "xxx",
    "generationType": "image",
    "modelId": "dall-e-3",
    "aiParams": {
      "resolution": "1024",
      "aspectRatio": "1:1"
    }
  }'

预期结果: 仅使用 AI 参数生成图片

2. AI + 业务参数请求

curl -X POST http://localhost:8000/api/v1/ai-conversations/{id}/generate \
  -H "Authorization: Bearer xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "messageId": "xxx",
    "generationType": "image",
    "modelId": "dall-e-3",
    "aiParams": {
      "resolution": "1024",
      "aspectRatio": "1:1",
      "seed": 42
    },
    "businessParams": {
      "customField1": "value1",
      "customField2": true
    }
  }'

预期结果: 使用 AI 参数生成图片 + 记录业务参数日志(待实现具体逻辑)


📝 后续工作

优先级 1: 前端适配(高)

前端需要适配新的请求格式:

// Before
const params = {
  modelId: 'dall-e-3',
  resolution: '1024',
  aspectRatio: '1:1',
  saveToProject: true
};

// After
const request = {
  modelId: 'dall-e-3',
  aiParams: {
    resolution: '1024',
    aspectRatio: '1:1'
  },
  businessParams: {  // 可选字典,字段自定义
    customField1: 'value1'
  }
};

优先级 2: 业务参数逻辑实现(中)

根据业务需求,实现 businessParams 的具体功能:

if business_params:
    # 根据业务需求实现具体逻辑
    # 示例字段(未来可能使用):
    # - saveToProject: 保存到项目
    # - autoPublish: 自动发布
    # - tagIds: 关联标签
    logger.info("收到业务参数(待实现): %s", business_params)

建议实现位置: ai_conversation_service.pytrigger_ai_generation 方法

优先级 3: 参数验证增强(中)

在 Service 层增加参数验证:

# 验证 AI 参数是否符合模型 capabilities
if not self._validate_ai_params(model_id, ai_params):
    raise ValidationError("参数不符合模型能力")

🔗 相关文档


📌 影响范围

破坏性变更 (Breaking Changes)

  • API 请求格式: 从单一 params 改为 modelId + aiParams + businessParams
  • 前端调用: 需要更新所有对话生成接口调用

建议迁移策略

1. 临时兼容期(可选)

如果需要兼容旧格式,可以在 Service 层增加兼容逻辑:

# 兼容旧格式
if 'params' in request_dict:
    params = request_dict['params']
    model_id = params.pop('modelId')
    ai_params = params
    business_params = None

2. 直接迁移(推荐)

直接要求前端适配新格式,避免维护兼容代码。


验证清单

  • Schema 定义(AIGenerationParams, BusinessGenerationParams, GenerateRequest
  • Service 层方法签名更新
  • Service 层参数处理逻辑更新
  • API Router 更新
  • Python 语法检查通过
  • Docker 服务重启成功
  • 前端适配新格式
  • 业务参数逻辑实现
  • 端到端测试

最新更新: 2026-02-13
版本: v1.0
状态: 已完成(待前端适配)