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.
7.0 KiB
7.0 KiB
AI Skill Prompt 格式强化 - 修复分镜未生成问题
日期: 2026-02-09
类型: Bug Fix
影响范围: AI 剧本解析、分镜生成
问题描述
现象
剧本解析成功提取了场景(locations),但没有生成分镜(storyboards):
{
"locations_created": 6,
"characters_created": 0,
"storyboards_created": 0 // ❌ 应该生成分镜
}
根本原因
AI 返回的数据格式不符合预期:
AI 实际返回格式(错误):
{
"scenes": [ // ❌ 使用了 scenes 而不是 locations
{
"scene_number": 1,
"location": "海边", // ❌ 使用了 location 字段而不是 name
"characters": ["女孩", "大盖帽"], // ❌ 角色嵌套在场景内
"shots": [...] // ❌ 镜头嵌套在场景内,而不是顶层 storyboards
}
]
}
期望格式(正确):
{
"characters": [...], // ✅ 顶层角色数组
"locations": [...], // ✅ 顶层场景数组
"storyboards": [...] // ✅ 顶层分镜数组
}
解决方案
方案选择
方案 1:增强数据转换逻辑(兼容多种格式)
方案 2:优化 AI Skill Prompt(从源头解决)✅
选择方案 2,因为:
- 从源头规范 AI 输出格式
- 代码逻辑更简单清晰
- 减少后期维护成本
实施内容
1. 强化 AI Skill Prompt 格式要求
文件: server/app/resources/ai_skills/screenplay_parsing.md
变更内容:
1.1 明确禁止的错误格式
⚠️ **禁止的错误格式**:
```json
// ❌ 错误:使用 scenes 而不是 locations
{"scenes": [...]}
// ❌ 错误:角色嵌套在场景内
{"locations": [{"characters": [...]}]}
// ❌ 错误:镜头嵌套在场景内
{"locations": [{"shots": [...]}]}
// ❌ 错误:场景对象使用 location 字段而不是 name
{"locations": [{"location": "海边"}]}
#### 1.2 增加格式检查清单
```markdown
**格式检查清单**(输出前必须自检):
- [ ] 是否有顶层 `characters` 数组?
- [ ] 是否有顶层 `locations` 数组(不是 `scenes`)?
- [ ] 是否有顶层 `storyboards` 数组(不是 `shots`)?
- [ ] `locations` 中的对象是否使用 `name` 字段(不是 `location` 或 `title`)?
- [ ] 角色是否在顶层数组,而不是嵌套在场景内?
- [ ] 分镜是否在顶层数组,而不是嵌套在场景内?
1.3 强调 7 个必需的顶层键
⚠️ **严格要求**: 必须返回以下7个顶层键,缺一不可:
1. **characters** - 顶层角色数组(不要嵌套在 scenes 内)
2. **character_tags** - 角色标签字典
3. **locations** - 顶层场景数组(禁止使用 "scenes")
4. **location_tags** - 场景标签字典
5. **props** - 顶层道具数组
6. **prop_tags** - 道具标签字典
7. **storyboards** - 顶层分镜数组(禁止使用 "shots" 或嵌套在 scenes 内)
2. 更新 AI Skill 版本
数据库更新:
UPDATE ai_skills_registry
SET version = '1.2.0'
WHERE name = 'screenplay_parsing';
版本历史:
1.2.0(2026-02-09): 强化输出格式要求,禁止嵌套格式,增加格式检查清单1.1.0(2026-02-08): 修复 locations/scenes 键名问题,强化格式要求1.0.0(2026-02-07): 初始版本,支持动态参数注入
验证步骤
1. 重置剧本解析状态
UPDATE screenplays
SET parsing_status = 0
WHERE screenplay_id = '019c4179-3dc6-7423-a30a-e965a7df0e09';
2. 重启 Celery Worker
docker restart jointo-server-celery-ai
3. 重新触发解析
curl 'http://localhost:6160/api/v1/screenplays/019c4179-3dc6-7423-a30a-e965a7df0e09/parse' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
--data-raw '{"custom_requirements":"","storyboard_count":6}'
4. 检查结果
期望输出:
{
"characters_created": > 0,
"locations_created": > 0,
"storyboards_created": > 0 // ✅ 应该有分镜生成
}
影响范围
受影响的组件
-
AI Skill Registry (
ai_skills_registry表)- 版本号更新为
1.2.0
- 版本号更新为
-
剧本解析任务 (
parse_screenplay_task)- 使用新版本的 AI Skill Prompt
-
前端分镜展示
- 解析成功后应该能看到生成的分镜
不受影响的组件
- 数据库 Schema(无变更)
- API 接口(无变更)
- 前端代码(无变更)
技术细节
AI Skill Prompt 加载流程
# server/app/tasks/ai_tasks.py (parse_screenplay_task)
# 1. 从数据库加载 AI Skill
skill = await skill_service.get_skill_by_name("screenplay_parsing")
system_prompt = skill['content']
# 2. 动态注入用户个性化要求
if custom_requirements:
system_prompt += f"""
## 用户特殊要求
{custom_requirements}
"""
# 3. 调用 AI Provider
result = await provider.process_text(
task_type='screenplay_parse',
text=screenplay_content,
output_format='json',
system_prompt=system_prompt
)
数据存储流程
# server/app/services/screenplay_service.py (store_parsed_elements)
# 1. 转换 AI 返回格式(兼容旧格式)
parsed_data = self._transform_ai_tags_format(parsed_data)
# 2. 创建项目元素(角色/场景/道具)
character_id_map = {...}
location_id_map = {...}
prop_id_map = {...}
# 3. 创建元素标签
tag_id_maps = {...}
# 4. 创建分镜(如果启用)
if auto_create_storyboards and parsed_data.get('storyboards'):
storyboard_ids = await self._create_storyboards_from_ai(...)
后续优化建议
1. 增加数据验证
在 parse_screenplay_task 中增加 AI 返回数据的格式验证:
def validate_ai_response(parsed_data: Dict[str, Any]) -> bool:
"""验证 AI 返回数据格式"""
required_keys = [
'characters', 'character_tags',
'locations', 'location_tags',
'props', 'prop_tags',
'storyboards'
]
for key in required_keys:
if key not in parsed_data:
logger.error(f"❌ AI 返回数据缺少必需键: {key}")
return False
# 检查是否使用了错误的键名
if 'scenes' in parsed_data:
logger.error("❌ AI 返回数据使用了 'scenes' 而不是 'locations'")
return False
return True
2. 增加降级策略
如果 AI 返回格式不正确,可以:
- 记录错误日志
- 尝试自动转换格式(方案 1)
- 通知用户重新解析
3. 监控 AI 输出质量
定期检查 AI 返回数据的格式合规性:
- 统计格式错误率
- 分析常见错误模式
- 持续优化 Prompt
相关文档
- AI Skill Prompt:
server/app/resources/ai_skills/screenplay_parsing.md - 剧本解析任务:
server/app/tasks/ai_tasks.py(parse_screenplay_task) - 剧本服务:
server/app/services/screenplay_service.py(store_parsed_elements) - 原始需求文档:
docs/prompts/screenplay-ai-parse-prompt.md
维护人员: AI Agent
最后更新: 2026-02-09