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.2 KiB
6.2 KiB
AI API 异常处理标准化
变更日期: 2026-02-11
变更类型: 重构 (Refactor)
影响范围: server/app/api/v1/ai.py
相关文档: API 响应格式标准化
📋 变更摘要
修复 ai.py 的异常处理不规范问题,删除所有手动 try-except 块,让 Service 层异常直接传播至 FastAPI 全局异常处理器。
核心问题
原代码存在 14 个路由,每个都包含冗余的异常捕获:
# ❌ 错误模式:手动捕获并重新抛出
try:
result = await service.generate_image(...)
return SuccessResponse(data=result)
except InsufficientCreditsError as e:
raise InsufficientCreditsError(str(e)) # 冗余
except ValidationError as e:
raise ValidationError(str(e)) # 冗余
except Exception as e:
raise HTTPException(500, "服务器内部错误") # 应由 Service 层处理
✅ 修复内容
1. 删除所有手动异常捕获
修改前(以 generate_image 为例):
@router.post("/generate-image")
async def generate_image(...):
service = AIService(db)
try:
result = await service.generate_image(...)
return SuccessResponse(data=result)
except InsufficientCreditsError as e:
raise InsufficientCreditsError(str(e))
except ValidationError as e:
raise ValidationError(str(e))
except Exception as e:
raise HTTPException(500, "服务器内部错误")
修改后:
@router.post("/generate-image")
async def generate_image(...):
"""生成图片
- **prompt**: 提示词(必填)
- **model**: 模型名称(可选)
"""
logger.info("收到图片生成请求: user_id=%s", current_user.user_id)
service = AIService(db)
result = await service.generate_image(
user_id=str(current_user.user_id),
prompt=request.prompt,
model=request.model,
# ...
)
logger.info("图片生成任务创建成功: job_id=%s", result['job_id'])
return SuccessResponse(data=result, message="图片生成任务创建成功")
2. 清理冗余导入
删除:
from fastapi import HTTPException, status # ❌ 删除
from app.core.exceptions import ValidationError, NotFoundError, InsufficientCreditsError # ❌ 删除
保留:
from app.core.logging import get_logger # ✅ 保留日志记录
from app.schemas.common import SuccessResponse # ✅ 保留标准响应
🎯 技术规范
Service 层职责
AIService负责抛出业务异常:InsufficientCreditsError- 积分不足ValidationError- 参数校验失败NotFoundError- 任务不存在NotImplementedError- 功能未实现InternalServerError- 服务器内部错误
API 层职责
- ✅ 做:接收请求、调用 Service、返回标准响应
- ✅ 做:记录请求日志(info/warning/error)
- ❌ 不做:捕获业务异常
- ❌ 不做:手动转换异常类型
FastAPI 全局异常处理器
# app/core/exception_handlers.py (已有配置)
@app.exception_handler(InsufficientCreditsError)
async def insufficient_credits_handler(request, exc):
return JSONResponse(
status_code=exc.status_code,
content={"code": 40302, "message": exc.detail}
)
📦 影响的路由 (14 个)
| 路由 | 方法 | 说明 |
|---|---|---|
/ai/generate-image |
POST | 生成图片 |
/ai/generate-video |
POST | 生成视频 |
/ai/generate-sound |
POST | 生成音效 |
/ai/generate-voice |
POST | 生成配音 |
/ai/voices |
GET | 获取音色列表 |
/ai/generate-subtitle |
POST | 生成字幕 |
/ai/process-text |
POST | 处理文本 |
/ai/jobs |
GET | 批量查询任务 |
/ai/jobs/{job_id} |
GET | 查询任务状态 |
/ai/jobs/{job_id}/cancel |
POST | 取消任务 |
/ai/statistics |
GET | 获取任务统计 |
/ai/usage/stats |
GET | 获取使用统计 |
/ai/queue/status |
GET | 获取队列状态 |
/ai/models |
GET | 获取可用模型 |
🔍 代码质量提升
行数优化
- 修改前: 430 行(含大量 try-except)
- 修改后: 290 行
- 减少: 140 行(-33%)
可读性提升
# ✅ 清晰的业务逻辑流(修改后)
async def generate_image(...):
logger.info("收到图片生成请求")
service = AIService(db)
result = await service.generate_image(...) # Service 层会抛异常
logger.info("图片生成任务创建成功")
return SuccessResponse(data=result) # FastAPI 自动处理异常
🧪 验证方法
1. 积分不足场景
# 请求
POST /api/v1/ai/generate-image
{
"prompt": "未来城市",
"width": 2048,
"height": 2048
}
# 响应(由 Service 层抛出,全局处理器捕获)
HTTP 403 Forbidden
{
"code": 40302,
"message": "积分不足,当前积分: 10,需要: 50",
"timestamp": "2026-02-11T10:30:00Z"
}
2. 参数校验失败
# 请求
POST /api/v1/ai/generate-video
{
"video_type": "text2video",
"prompt": "" # 空提示词
}
# 响应(由 Service 层抛出)
HTTP 422 Unprocessable Entity
{
"code": 42201,
"message": "prompt 不能为空",
"timestamp": "2026-02-11T10:31:00Z"
}
3. 任务不存在
# 请求
GET /api/v1/ai/jobs/nonexistent-job-id
# 响应(由 Service 层抛出)
HTTP 404 Not Found
{
"code": 40401,
"message": "任务不存在",
"timestamp": "2026-02-11T10:32:00Z"
}
🔗 相关链接
📌 注意事项
- 不影响现有功能:异常仍会被正确处理,只是处理位置从 API 层移至全局
- 日志保留:所有
logger.info/warning/error调用均保留,用于追踪请求流程 - 向后兼容:响应格式完全不变,前端无需修改
变更人: Claude
审核人: 待定
部署状态: ✅ 已完成