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.
 

5.8 KiB

AI Jobs API 响应字段 camelCase 修复

日期: 2026-02-06
类型: Bug Fix
影响范围: AI Jobs API (server/app/api/v1/ai_jobs.py)

问题描述

AI Jobs API 的所有端点返回的响应字段使用 snake_case,不符合 API 设计规范要求的 camelCase 格式。

根本原因

  1. API 层直接返回 Service 层的 snake_case 字典,未经过 Pydantic Schema 序列化
  2. 部分响应 Schema 缺失(AIJobListItemResponseAIJobStatisticsResponse
  3. 路由注册顺序问题:ai.routerai_jobs.router 之前注册,导致 ai.py 中的旧路由覆盖新路由
  4. 代码中使用 current_user['user_id'] 而不是 current_user.user_idget_current_user 返回 User 对象而非字典)

修复内容

1. 新增 Schema (server/app/schemas/ai.py)

创建了两个新的响应 Schema:

AIJobListItemResponse

class AIJobListItemResponse(BaseModel):
    """AI 任务列表项响应"""
    job_id: str = Field(..., alias="jobId")
    job_type: int = Field(..., alias="jobType")
    status: int
    progress: int
    model_name: Optional[str] = Field(None, alias="modelName")
    credits_used: int = Field(..., alias="creditsUsed")
    created_at: str = Field(..., alias="createdAt")
    started_at: Optional[str] = Field(None, alias="startedAt")
    completed_at: Optional[str] = Field(None, alias="completedAt")
    error_message: Optional[str] = Field(None, alias="errorMessage")
    
    model_config = ConfigDict(populate_by_name=True)

AIJobStatisticsResponse

class AIJobStatisticsResponse(BaseModel):
    """AI 任务统计响应"""
    total_jobs: int = Field(..., alias="totalJobs")
    completed_jobs: int = Field(..., alias="completedJobs")
    failed_jobs: int = Field(..., alias="failedJobs")
    pending_jobs: int = Field(..., alias="pendingJobs")
    processing_jobs: int = Field(..., alias="processingJobs")
    success_rate: float = Field(..., alias="successRate")
    total_credits: int = Field(..., alias="totalCredits")
    avg_execution_time: float = Field(..., alias="avgExecutionTime")
    by_type: Dict[str, Any] = Field(..., alias="byType")
    by_model: Dict[str, Any] = Field(..., alias="byModel")
    
    model_config = ConfigDict(populate_by_name=True)

2. 修改 API 层 (server/app/api/v1/ai_jobs.py)

添加 Schema 导入

from app.schemas.ai import (
    AIJobStatusResponse,
    AIJobListItemResponse,
    AIJobStatisticsResponse,
    UsageStatsResponse,
)

修改的端点

GET /ai/jobs/{job_id} - 查询任务状态

# 修改前:
return success_response(data=result)

# 修改后:
job_data = AIJobStatusResponse.model_validate(result).model_dump(by_alias=True, mode='json')
return success_response(data=job_data)

GET /ai/jobs - 批量查询用户任务

# 修改前:
return success_response(data=result)

# 修改后:
serialized_items = [
    AIJobListItemResponse.model_validate(item).model_dump(by_alias=True, mode='json')
    for item in result['items']
]
response_data = {
    "items": serialized_items,
    "total": result['total'],
    "page": result['page'],
    "pageSize": result['page_size'],
    "totalPages": result['total_pages']
}
return success_response(data=response_data)

GET /ai/jobs/statistics - 获取任务统计信息

# 修改前:
return success_response(data=result)

# 修改后:
stats_data = AIJobStatisticsResponse.model_validate(result).model_dump(by_alias=True, mode='json')
return success_response(data=stats_data)

GET /ai/jobs/usage/stats - 获取使用统计

# 修改前:
return success_response(data=result)

# 修改后:
usage_data = UsageStatsResponse.model_validate(result).model_dump(by_alias=True, mode='json')
return success_response(data=usage_data)

验证结果

所有 Schema 的 camelCase 序列化已验证正确:

  • AIJobStatusResponse: jobId, jobType, modelName, creditsUsed, createdAt, updatedAt, startedAt, completedAt, errorMessage, inputData, outputData
  • AIJobListItemResponse: 所有字段使用 camelCase
  • AIJobStatisticsResponse: totalJobs, completedJobs, failedJobs, pendingJobs, processingJobs, successRate, totalCredits, avgExecutionTime, byType, byModel
  • UsageStatsResponse: totalCost, totalCreditsUsed, totalRequests, byModel, byType

测试状态

所有集成测试通过 (在 Docker 环境中运行):

  1. test_list_jobs_returns_camelcase - 验证列表响应字段使用 camelCase
  2. test_get_statistics_returns_camelcase - 验证统计响应字段使用 camelCase
  3. test_get_usage_stats_returns_camelcase - 验证使用统计响应字段使用 camelCase
  4. 代码无 linter 错误
  5. Schema 序列化验证通过

影响范围

破坏性变更

此修复会影响所有调用 AI Jobs API 的客户端:

  • 影响端点:

    • GET /api/v1/ai/jobs/{job_id}
    • GET /api/v1/ai/jobs
    • GET /api/v1/ai/jobs/statistics
    • GET /api/v1/ai/jobs/usage/stats
  • 客户端适配: 前端代码需要更新字段名从 snake_case 改为 camelCase

未修改部分

  • Service 层:保持 snake_case(内部实现)
  • Repository 层:保持不变
  • 数据库:保持不变

后续工作

  1. 修复 AI Jobs API 响应字段格式
  2. 在 Docker 环境运行完整的集成测试
  3. 更新前端代码以适配新的字段名
  4. 验证其他 API 端点的字段格式一致性(如 ai.py 中的旧路由)
  5. 考虑废弃 ai.py 中的 /jobs 路由,统一使用 ai_jobs.py

参考