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.
11 KiB
11 KiB
AI Conversation API 字段命名规范修复
📋 基本信息
- 日期: 2026-02-06
- 类型: 规范修复
- 影响范围: AI Conversation 模块 API 层和 Service 层
- 破坏性变更: ⚠️ 是 - API 响应字段名从部分 camelCase 改为完全 camelCase
🎯 修复目标
确保 AI Conversation 模块所有 API 响应字段使用 camelCase 命名规范,符合 jointo-tech-stack 规范要求。
📊 问题分析
当前状态
- ✅ API 层部分端点已手动转换字段名为 camelCase
- ⚠️ Service 层手动构建响应字典(不符合规范)
- ⚠️
get_mentionable_resources返回 snake_case 字段 - ❌ 缺少 Pydantic Response Schema(无类型安全保证)
目标状态
- ✅ 所有 API 响应字段使用 camelCase
- ✅ 使用 Pydantic Schema 提供类型验证
- ✅ Service 层返回格式化字典(兼容现有逻辑)
- ✅ 完整的单元测试和集成测试覆盖
🔧 修复内容
1. Schema 层修改
1.1 创建 Conversation Response Schemas
文件: server/app/schemas/ai_conversation.py
class ConversationResponse(BaseModel):
"""对话会话响应模型"""
conversation_id: UUID = Field(..., alias="conversationId")
user_id: UUID = Field(..., alias="userId")
project_id: Optional[UUID] = Field(None, alias="projectId")
target_type: int = Field(..., alias="targetType")
target_id: UUID = Field(..., alias="targetId")
tag_id: Optional[UUID] = Field(None, alias="tagId")
media_type: int = Field(..., alias="mediaType")
title: Optional[str] = Field(None)
status: int = Field(...)
message_count: int = Field(..., alias="messageCount")
last_message_at: Optional[datetime] = Field(None, alias="lastMessageAt")
created_at: datetime = Field(..., alias="createdAt")
updated_at: datetime = Field(..., alias="updatedAt")
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
class ConversationListItem(BaseModel):
"""对话会话列表项"""
conversation_id: UUID = Field(..., alias="conversationId")
title: Optional[str] = Field(None)
target_type: int = Field(..., alias="targetType")
target_id: UUID = Field(..., alias="targetId")
tag_id: Optional[UUID] = Field(None, alias="tagId")
media_type: int = Field(..., alias="mediaType")
status: int = Field(...)
message_count: int = Field(..., alias="messageCount")
last_message_at: Optional[datetime] = Field(None, alias="lastMessageAt")
created_at: datetime = Field(..., alias="createdAt")
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
1.2 修复 TriggerAIGenerationResponse
文件: server/app/schemas/ai_conversation_message.py
变更:
# 修改前
job_id: UUID = Field(..., alias="jobId")
# 修改后
job_id: str = Field(..., alias="jobId") # 与 service 返回类型一致
2. API 层修改
文件: server/app/api/v1/ai_conversations.py
2.1 导入新 Schemas
from app.schemas.ai_conversation import (
ConversationCreateRequest,
ConversationUpdateRequest,
ConversationResponse,
ConversationListItem,
MessageCreateRequest,
GenerateRequest
)
from app.schemas.ai_conversation_message import (
AIConversationMessageResponse,
AIConversationMessageListItem,
TriggerAIGenerationResponse
)
2.2 修改所有端点使用 Pydantic 序列化
| 端点 | 修改内容 |
|---|---|
POST /conversations |
使用 ConversationResponse 序列化 |
GET /conversations |
列表项使用 ConversationListItem 序列化 |
GET /conversations/{id} |
使用 ConversationResponse 序列化 |
PATCH /conversations/{id} |
使用 ConversationResponse 序列化 |
POST /conversations/{id}/messages |
使用 AIConversationMessageResponse 序列化 |
GET /conversations/{id}/messages |
列表项使用 AIConversationMessageListItem 序列化 |
POST /conversations/{id}/generate |
使用 TriggerAIGenerationResponse 序列化 |
修改示例:
# 修改前
async def create_conversation(...):
result = await service.create_conversation(...)
return success_response(data=result)
# 修改后
async def create_conversation(...):
result = await service.create_conversation(...)
conversation_response = ConversationResponse.model_validate(result)
return success_response(
data=conversation_response.model_dump(by_alias=True, mode='json')
)
3. Service 层修改
文件: server/app/services/ai_conversation_service.py
3.1 修复 get_mentionable_resources 返回字段
将所有 snake_case 字段改为 camelCase:
# 修改前
return {
'conversation': {
'conversation_id': str(conversation.conversation_id),
'target_type': conversation.target_type,
'target_id': str(conversation.target_id),
'target_name': target_name
},
'resources': [
{
'type': 'character',
'element_id': str(char_id),
'element_name': char_name,
'has_tags': True,
'tags': [...],
'default_resource': {...}
}
]
}
# 修改后
return {
'conversation': {
'conversationId': str(conversation.conversation_id),
'targetType': conversation.target_type,
'targetId': str(conversation.target_id),
'targetName': target_name
},
'resources': [
{
'type': 'character',
'elementId': str(char_id),
'elementName': char_name,
'hasTags': True,
'tags': [...],
'defaultResource': {...}
}
]
}
3.2 修复资源元数据字段
在以下方法中统一修改字段名:
_get_storyboard_mentionable_resources_get_character_mentionable_resources_get_scene_mentionable_resources_get_prop_mentionable_resources
字段映射:
resource_id → resourceId
resource_url → resourceUrl
thumbnail_url → thumbnailUrl
tag_id → tagId
tag_label → tagLabel
element_id → elementId
element_name → elementName
has_tags → hasTags
default_resource → defaultResource
4. 测试代码
4.1 单元测试
文件: server/tests/test_ai_conversation_response_fields.py
覆盖内容:
- ✅
ConversationResponsecamelCase 验证 - ✅
ConversationListItemcamelCase 验证 - ✅
AIConversationMessageResponsecamelCase 验证 - ✅
AIConversationMessageListItemcamelCase 验证 - ✅
TriggerAIGenerationResponsecamelCase 验证 - ✅ Datetime 字段序列化为 ISO 字符串
- ✅ UUID 字段序列化为字符串
测试结果:
$ pytest tests/test_ai_conversation_response_fields.py -v
7 passed in 0.06s ✅
4.2 集成测试
文件: server/tests/integration/test_ai_conversation_api.py
状态: 已存在,使用 camelCase 断言 执行状态: 因 pytest-asyncio 事件循环问题暂时无法运行(已知问题,不影响代码正确性)
📈 测试覆盖率
单元测试
- ✅ Schema 序列化验证: 7/7 通过
- ✅ 字段命名规范检查: 完整覆盖
- ✅ 类型转换验证: 完整覆盖
集成测试
- ⏸️ API 端点测试: 待环境修复后验证
- ✅ 现有测试已使用 camelCase 断言
🔍 验证方法
手动验证 API 响应
# 1. 启动服务
docker-compose up -d
# 2. 创建对话会话
curl -X POST http://localhost:8000/api/v1/ai/conversations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"targetType": 1,
"targetId": "uuid-here",
"mediaType": 1
}'
# 3. 验证响应字段为 camelCase
# 预期输出:
{
"code": 200,
"data": {
"conversationId": "...", # ✅ camelCase
"userId": "...", # ✅ camelCase
"targetType": 1, # ✅ camelCase
"targetId": "...", # ✅ camelCase
"mediaType": 1, # ✅ camelCase
"messageCount": 0, # ✅ camelCase
"createdAt": "...", # ✅ camelCase
"updatedAt": "..." # ✅ camelCase
}
}
⚠️ 破坏性变更
前端需要修改的字段
对话会话响应
// 修改前
interface ConversationResponse {
conversation_id: string;
user_id: string;
target_type: number;
target_id: string;
tag_id?: string;
media_type: number;
message_count: number;
last_message_at?: string;
created_at: string;
updated_at: string;
}
// 修改后
interface ConversationResponse {
conversationId: string; // ✅
userId: string; // ✅
targetType: number; // ✅
targetId: string; // ✅
tagId?: string; // ✅
mediaType: number; // ✅
messageCount: number; // ✅
lastMessageAt?: string; // ✅
createdAt: string; // ✅
updatedAt: string; // ✅
}
可提及资源响应
// 修改前
interface MentionableResource {
element_id: string;
element_name: string;
has_tags: boolean;
default_resource?: ResourceInfo;
tags?: TagInfo[];
}
// 修改后
interface MentionableResource {
elementId: string; // ✅
elementName: string; // ✅
hasTags: boolean; // ✅
defaultResource?: ResourceInfo; // ✅
tags?: TagInfo[];
}
📝 涉及文件清单
修改的文件
server/app/schemas/ai_conversation.py- 新增 Response Schemasserver/app/schemas/ai_conversation_message.py- 修复job_id类型server/app/api/v1/ai_conversations.py- 所有端点使用 Pydantic 序列化server/app/services/ai_conversation_service.py- 修复get_mentionable_resources字段名
新增的文件
server/tests/test_ai_conversation_response_fields.py- Schema 单元测试docs/server/changelogs/2026-02-06-ai-conversation-api-camelcase-fix.md- 本文档
需要同步更新的文件(前端)
client/src/types/ai-conversation.ts- 接口类型定义client/src/services/api/ai-conversations.ts- API 调用代码client/src/hooks/useAIConversation.ts- 相关 hooks
🎓 经验总结
最佳实践
- ✅ 始终使用 Pydantic Schema: 提供类型安全和自动序列化
- ✅ 统一字段命名规范: API 层统一使用 camelCase
- ✅ 先写测试后修改: 单元测试先行,确保修改正确性
- ✅ Service 层格式化: 虽然保留了字典格式化,但 API 层用 Pydantic 验证
避免的陷阱
- ❌ 不要在 Service 层手动构建字典并混用命名规范
- ❌ 不要忽略 IntEnum 类型转换(如
role,status) - ❌ 不要混用 UUID 和 str 类型(API 响应统一用 str)
🔄 后续优化建议
-
完全重构 Service 层
- 移除
_format_*方法 - 直接返回 SQLModel 对象
- API 层统一使用 Pydantic 序列化
- 移除
-
增强类型安全
- 使用 TypedDict 定义 Service 层返回类型
- 添加 mypy 静态类型检查
-
完善测试覆盖
- 修复 pytest-asyncio 事件循环问题
- 运行完整集成测试套件
✅ 验收标准
- 所有 API 响应字段使用 camelCase
- 使用 Pydantic Schema 提供类型验证
- 单元测试全部通过 (7/7)
- 创建完整文档
- 集成测试全部通过(待环境修复)
- 前端代码同步更新
📞 联系方式
如有疑问,请联系:
- 负责人:AI Agent
- 文档更新日期:2026-02-06