# 剧本 AI 解析格式兼容性修复 **日期**: 2026-02-09 **类型**: Bug Fix **影响范围**: 剧本 AI 解析功能 ## 问题描述 ### 🐛 **核心问题** 剧本 AI 解析功能无法正确处理 AI 返回的数据格式,导致: - ❌ 0 个角色被创建 - ❌ 0 个场景被创建 - ❌ 0 个道具被创建 - ❌ 0 个分镜被创建 ### 📋 **问题根因** AI 实际返回的数据格式与代码期望的格式不匹配: **AI 实际返回格式**: ```json { "scenes": [ // ❌ 使用了 "scenes" 键名 { "scene_number": 1, "location": "海边", // ❌ 使用了 "location" 字段而不是 "name" "time": "晨", "description": "...", "characters": ["女孩", "渔民", "老警察", "小警察"], "shots": [...] } ] } ``` **代码期望格式**: ```json { "locations": [ // ✅ 应该使用 "locations" 键名 { "name": "海边", // ✅ 应该使用 "name" 字段 "location": "海边", "description": "...", "meta_data": { "time_of_day": "morning", "scene_number": 1 } } ], "characters": [...], "props": [...] } ``` ### 🔍 **日志证据** ```log [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 转换逻辑** ```python # 步骤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 实际使用的字段) ```python # 兼容 name/title/location 字段 loc_name = location.get('name') or location.get('title') or location.get('location') ``` ### 📊 **支持的格式** 修复后,`_transform_ai_tags_format()` 方法支持三种格式: 1. **格式1(顶层格式 - AI Skill Prompt 标准格式)**: - 直接使用,无需转换 - 包含 `character_tags`、`location_tags`、`prop_tags` 2. **格式2(嵌套格式 - 旧版格式)**: - 标签嵌套在元素对象内 - 需要提取并转换为顶层格式 3. **格式3(AI 实际返回格式 - 新增支持)**: - 使用 `scenes` 而不是 `locations` - 场景对象使用 `location` 字段而不是 `name` - 自动转换为标准格式 ## 测试验证 ### ✅ **验证步骤** 1. 重新解析剧本 `019c4104-7231-75c0-9420-a7d143465f0e` 2. 检查日志确认格式转换成功 3. 验证数据库中创建的元素数量 ### 📈 **预期结果** - ✅ 成功识别并转换 `scenes` 为 `locations` - ✅ 正确提取场景名称(从 `location` 字段) - ✅ 创建角色、场景、道具、标签、分镜 ## 影响范围 ### 📦 **修改文件** - `server/app/services/screenplay_service.py` - 修改 `_transform_ai_tags_format()` 方法 ### 🔄 **向后兼容性** - ✅ 完全向后兼容 - ✅ 不影响现有格式的处理 - ✅ 仅新增对 AI 实际返回格式的支持 ## 后续优化建议 1. **统一 AI Prompt**:更新 AI Skill Prompt,确保返回标准格式(使用 `locations` 而不是 `scenes`) 2. **增强日志**:添加更详细的格式检测和转换日志 3. **单元测试**:为 `_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`