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.
4.9 KiB
4.9 KiB
剧本 AI 解析格式兼容性修复
日期: 2026-02-09
类型: Bug Fix
影响范围: 剧本 AI 解析功能
问题描述
🐛 核心问题
剧本 AI 解析功能无法正确处理 AI 返回的数据格式,导致:
- ❌ 0 个角色被创建
- ❌ 0 个场景被创建
- ❌ 0 个道具被创建
- ❌ 0 个分镜被创建
📋 问题根因
AI 实际返回的数据格式与代码期望的格式不匹配:
AI 实际返回格式:
{
"scenes": [ // ❌ 使用了 "scenes" 键名
{
"scene_number": 1,
"location": "海边", // ❌ 使用了 "location" 字段而不是 "name"
"time": "晨",
"description": "...",
"characters": ["女孩", "渔民", "老警察", "小警察"],
"shots": [...]
}
]
}
代码期望格式:
{
"locations": [ // ✅ 应该使用 "locations" 键名
{
"name": "海边", // ✅ 应该使用 "name" 字段
"location": "海边",
"description": "...",
"meta_data": {
"time_of_day": "morning",
"scene_number": 1
}
}
],
"characters": [...],
"props": [...]
}
🔍 日志证据
[2026-02-09 06:44:30] 剧本解析完成: characters=0, locations=6, props=0, storyboards=0
[2026-02-09 06:44:32] WARNING: 场景缺少 name/title 字段,跳过: {'scene_number': 1, 'location': '海边', ...}
[2026-02-09 06:44:32] 剧本元素存储成功: 角色=0, 场景=0, 道具=0, 标签=0, 分镜=0
解决方案
✅ 修复内容
修改 server/app/services/screenplay_service.py 中的 _transform_ai_tags_format() 方法,增强格式兼容性:
1. 新增 scenes → locations 转换逻辑
# 步骤1:将 scenes 转换为 locations(如果存在)
if 'scenes' in parsed_data and not parsed_data.get('locations'):
logger.info("检测到 AI 返回 'scenes' 格式,转换为 'locations'")
scenes = parsed_data['scenes']
locations = []
for scene in scenes:
# 从 scene 对象中提取 location 字段作为 name
location_name = scene.get('location') or scene.get('name') or scene.get('title')
if not location_name:
logger.warning("场景缺少 location/name/title 字段,跳过: %s", scene)
continue
# 构建标准的 location 对象
location_obj = {
'name': location_name, # ✅ 使用 name 字段
'location': location_name,
'description': scene.get('description', ''),
'meta_data': {
'scene_number': scene.get('scene_number'),
'time': scene.get('time'),
'time_of_day': scene.get('time_of_day'),
'characters': scene.get('characters', []),
'shots': scene.get('shots', [])
}
}
locations.append(location_obj)
result['locations'] = locations
2. 增强字段名兼容性
支持从以下字段提取场景名称:
name(标准字段)title(备选字段)location(AI 实际使用的字段)
# 兼容 name/title/location 字段
loc_name = location.get('name') or location.get('title') or location.get('location')
📊 支持的格式
修复后,_transform_ai_tags_format() 方法支持三种格式:
-
格式1(顶层格式 - AI Skill Prompt 标准格式):
- 直接使用,无需转换
- 包含
character_tags、location_tags、prop_tags
-
格式2(嵌套格式 - 旧版格式):
- 标签嵌套在元素对象内
- 需要提取并转换为顶层格式
-
格式3(AI 实际返回格式 - 新增支持):
- 使用
scenes而不是locations - 场景对象使用
location字段而不是name - 自动转换为标准格式
- 使用
测试验证
✅ 验证步骤
- 重新解析剧本
019c4104-7231-75c0-9420-a7d143465f0e - 检查日志确认格式转换成功
- 验证数据库中创建的元素数量
📈 预期结果
- ✅ 成功识别并转换
scenes为locations - ✅ 正确提取场景名称(从
location字段) - ✅ 创建角色、场景、道具、标签、分镜
影响范围
📦 修改文件
server/app/services/screenplay_service.py- 修改
_transform_ai_tags_format()方法
- 修改
🔄 向后兼容性
- ✅ 完全向后兼容
- ✅ 不影响现有格式的处理
- ✅ 仅新增对 AI 实际返回格式的支持
后续优化建议
- 统一 AI Prompt:更新 AI Skill Prompt,确保返回标准格式(使用
locations而不是scenes) - 增强日志:添加更详细的格式检测和转换日志
- 单元测试:为
_transform_ai_tags_format()方法添加单元测试,覆盖三种格式
相关文档
- AI Skill Prompt:
server/app/tasks/ai_tasks.py(parse_screenplay_task) - 剧本解析流程:
docs/requirements/backend/04-services/project/screenplay-service.md